/*
 * 86Box    A hypervisor and IBM PC system emulator that specializes in
 *          running old operating systems and software designed for IBM
 *          PC systems and compatibles from 1981 through fairly recent
 *          system designs based on the PCI bus.
 *
 *          This file is part of the 86Box distribution.
 *
 *          Implementation of PS/2 series Mouse devices.
 *
 * Authors: Miran Grca, <mgrca8@gmail.com>
 *          Fred N. van Kempen, <decwiz@yahoo.com>
 *
 *          Copyright 2016-2023 Miran Grca.
 *          Copyright 2017-2023 Fred N. van Kempen.
 */
#include <stdarg.h>
#include <stdio.h>
#include <stdint.h>
#include <string.h>
#include <stdlib.h>
#include <wchar.h>
#define HAVE_STDARG_H
#include <86box/86box.h>
#include <86box/device.h>
#include <86box/keyboard.h>
#include <86box/mouse.h>

#define FLAG_PS2       0x08  /* dev is AT or PS/2 */
#define FLAG_AT        0x00  /* dev is AT or PS/2 */
#define FLAG_TYPE_MASK 0x07  /* mask for type     */

#define FIFO_SIZE      16

#define BAT_COUNT      1000

enum {
    KBD_84_KEY = 0,
    KBD_101_KEY,
    KBD_102_KEY,
    KBD_JIS,
    KBD_KOREAN
};

#define FLAG_ENABLED 0x10  /* dev is enabled for use */
#define FLAG_CTRLDAT 0x08  /* ctrl or data mode */

const uint8_t id_bytes[16][4] = { { 0x00, 0x00, 0x00, 0x00 },    /* AT 84-key */
                                  { 0x00, 0x00, 0x00, 0x00 },    /* AT 101/102/106-key */
                                  { 0x00, 0x00, 0x00, 0x00 },
                                  { 0x00, 0x00, 0x00, 0x00 },
                                  { 0x00, 0x00, 0x00, 0x00 },    /* AT Korean */
                                  { 0x00, 0x00, 0x00, 0x00 },
                                  { 0x00, 0x00, 0x00, 0x00 },
                                  { 0x00, 0x00, 0x00, 0x00 },
                                  { 0x00, 0x00, 0x00, 0x00 },
                                  { 0xab, 0x83, 0x00, 0x00 },    /* PS/2 101-key */
                                  { 0xab, 0x83, 0x00, 0x00 },    /* PS/2 102-key */
                                  { 0xab, 0x90, 0x00, 0x00 },    /* PS/2 106-key JIS */
                                  /* Japanese keyboard ID - TODO: Find the actual Korean one. */
                                  { 0xab, 0x90, 0x00, 0x00 },    /* PS/2 Korean */
                                  { 0x00, 0x00, 0x00, 0x00 },
                                  { 0x00, 0x00, 0x00, 0x00 },
                                  { 0x00, 0x00, 0x00, 0x00 } };

/* Global keyboard flags for scan code set 3:
   bit 0 = repeat, bit 1 = makes break code? */
uint8_t keyboard_set3_flags[512];
uint8_t keyboard_set3_all_repeat;
uint8_t keyboard_set3_all_break;

/* Global keyboard mode:
   Bits 0 - 1 = scan code set. */
uint8_t keyboard_mode = 0x02;

static atkbc_dev_t *SavedKbd                        = NULL;

static uint8_t     inv_cmd_response                 = 0xfa;

static uint16_t    bat_counter                      = 0;

static const scancode scancode_set1[512] = {
  // clang-format off
    { {          0},{               0} }, { {     0x01,0},{          0x81,0} }, { {     0x02,0},{          0x82,0} }, { {     0x03,0},{          0x83,0} },        /*000*/
    { {     0x04,0},{          0x84,0} }, { {     0x05,0},{          0x85,0} }, { {     0x06,0},{          0x86,0} }, { {     0x07,0},{          0x87,0} },        /*004*/
    { {     0x08,0},{          0x88,0} }, { {     0x09,0},{          0x89,0} }, { {     0x0a,0},{          0x8a,0} }, { {     0x0b,0},{          0x8b,0} },        /*008*/
    { {     0x0c,0},{          0x8c,0} }, { {     0x0d,0},{          0x8d,0} }, { {     0x0e,0},{          0x8e,0} }, { {     0x0f,0},{          0x8f,0} },        /*00c*/
    { {     0x10,0},{          0x90,0} }, { {     0x11,0},{          0x91,0} }, { {     0x12,0},{          0x92,0} }, { {     0x13,0},{          0x93,0} },        /*010*/
    { {     0x14,0},{          0x94,0} }, { {     0x15,0},{          0x95,0} }, { {     0x16,0},{          0x96,0} }, { {     0x17,0},{          0x97,0} },        /*014*/
    { {     0x18,0},{          0x98,0} }, { {     0x19,0},{          0x99,0} }, { {     0x1a,0},{          0x9a,0} }, { {     0x1b,0},{          0x9b,0} },        /*018*/
    { {     0x1c,0},{          0x9c,0} }, { {     0x1d,0},{          0x9d,0} }, { {     0x1e,0},{          0x9e,0} }, { {     0x1f,0},{          0x9f,0} },        /*01c*/
    { {     0x20,0},{          0xa0,0} }, { {     0x21,0},{          0xa1,0} }, { {     0x22,0},{          0xa2,0} }, { {     0x23,0},{          0xa3,0} },        /*020*/
    { {     0x24,0},{          0xa4,0} }, { {     0x25,0},{          0xa5,0} }, { {     0x26,0},{          0xa6,0} }, { {     0x27,0},{          0xa7,0} },        /*024*/
    { {     0x28,0},{          0xa8,0} }, { {     0x29,0},{          0xa9,0} }, { {     0x2a,0},{          0xaa,0} }, { {     0x2b,0},{          0xab,0} },        /*028*/
    { {     0x2c,0},{          0xac,0} }, { {     0x2d,0},{          0xad,0} }, { {     0x2e,0},{          0xae,0} }, { {     0x2f,0},{          0xaf,0} },        /*02c*/
    { {     0x30,0},{          0xb0,0} }, { {     0x31,0},{          0xb1,0} }, { {     0x32,0},{          0xb2,0} }, { {     0x33,0},{          0xb3,0} },        /*030*/
    { {     0x34,0},{          0xb4,0} }, { {     0x35,0},{          0xb5,0} }, { {     0x36,0},{          0xb6,0} }, { {     0x37,0},{          0xb7,0} },        /*034*/
    { {     0x38,0},{          0xb8,0} }, { {     0x39,0},{          0xb9,0} }, { {     0x3a,0},{          0xba,0} }, { {     0x3b,0},{          0xbb,0} },        /*038*/
    { {     0x3c,0},{          0xbc,0} }, { {     0x3d,0},{          0xbd,0} }, { {     0x3e,0},{          0xbe,0} }, { {     0x3f,0},{          0xbf,0} },        /*03c*/
    { {     0x40,0},{          0xc0,0} }, { {     0x41,0},{          0xc1,0} }, { {     0x42,0},{          0xc2,0} }, { {     0x43,0},{          0xc3,0} },        /*040*/
    { {     0x44,0},{          0xc4,0} }, { {     0x45,0},{          0xc5,0} }, { {     0x46,0},{          0xc6,0} }, { {     0x47,0},{          0xc7,0} },        /*044*/
    { {     0x48,0},{          0xc8,0} }, { {     0x49,0},{          0xc9,0} }, { {     0x4a,0},{          0xca,0} }, { {     0x4b,0},{          0xcb,0} },        /*048*/
    { {     0x4c,0},{          0xcc,0} }, { {     0x4d,0},{          0xcd,0} }, { {     0x4e,0},{          0xce,0} }, { {     0x4f,0},{          0xcf,0} },        /*04c*/
    { {     0x50,0},{          0xd0,0} }, { {     0x51,0},{          0xd1,0} }, { {     0x52,0},{          0xd2,0} }, { {     0x53,0},{          0xd3,0} },        /*050*/
    { {     0x54,0},{          0xd4,0} }, { {     0x55,0},{          0xd5,0} }, { {     0x56,0},{          0xd6,0} }, { {     0x57,0},{          0xd7,0} },        /*054*/
    { {     0x58,0},{          0xd8,0} }, { {     0x59,0},{          0xd9,0} }, { {     0x5a,0},{          0xda,0} }, { {     0x5b,0},{          0xdb,0} },        /*058*/
    { {     0x5c,0},{          0xdc,0} }, { {     0x5d,0},{          0xdd,0} }, { {     0x5e,0},{          0xde,0} }, { {     0x5f,0},{          0xdf,0} },        /*05c*/
    { {     0x60,0},{          0xe0,0} }, { {     0x61,0},{          0xe1,0} }, { {     0x62,0},{          0xe2,0} }, { {     0x63,0},{          0xe3,0} },        /*060*/
    { {     0x64,0},{          0xe4,0} }, { {     0x65,0},{          0xe5,0} }, { {     0x66,0},{          0xe6,0} }, { {     0x67,0},{          0xe7,0} },        /*064*/
    { {     0x68,0},{          0xe8,0} }, { {     0x69,0},{          0xe9,0} }, { {     0x6a,0},{          0xea,0} }, { {     0x6b,0},{          0xeb,0} },        /*068*/
    { {     0x6c,0},{          0xec,0} }, { {     0x6d,0},{          0xed,0} }, { {     0x6e,0},{          0xee,0} }, { {     0x6f,0},{          0xef,0} },        /*06c*/
    { {     0x70,0},{          0xf0,0} }, { {     0x71,0},{          0xf1,0} }, { {     0x72,0},{          0xf2,0} }, { {     0x73,0},{          0xf3,0} },        /*070*/
    { {     0x74,0},{          0xf4,0} }, { {     0x75,0},{          0xf5,0} }, { {     0x76,0},{          0xf6,0} }, { {     0x77,0},{          0xf7,0} },        /*074*/
    { {     0x78,0},{          0xf8,0} }, { {     0x79,0},{          0xf9,0} }, { {     0x7a,0},{          0xfa,0} }, { {     0x7b,0},{          0xfb,0} },        /*078*/
    { {     0x7c,0},{          0xfc,0} }, { {     0x7d,0},{          0xfd,0} }, { {     0x7e,0},{          0xfe,0} }, { {     0x7f,0},{          0xff,0} },        /*07c*/

    { {     0x80,0},{               0} }, { {     0x81,0},{               0} }, { {     0x82,0},{               0} }, { {          0},{               0} },        /*080*/
    { {          0},{               0} }, { {     0x85,0},{               0} }, { {     0x86,0},{               0} }, { {     0x87,0},{               0} },        /*084*/
    { {     0x88,0},{               0} }, { {     0x89,0},{               0} }, { {     0x8a,0},{               0} }, { {     0x8b,0},{               0} },        /*088*/
    { {     0x8c,0},{               0} }, { {     0x8d,0},{               0} }, { {     0x8e,0},{               0} }, { {     0x8f,0},{               0} },        /*08c*/
    { {     0x90,0},{               0} }, { {     0x91,0},{               0} }, { {     0x92,0},{               0} }, { {     0x93,0},{               0} },        /*090*/
    { {     0x94,0},{               0} }, { {     0x95,0},{               0} }, { {     0x96,0},{               0} }, { {     0x97,0},{               0} },        /*094*/
    { {     0x98,0},{               0} }, { {     0x99,0},{               0} }, { {     0x9a,0},{               0} }, { {     0x9b,0},{               0} },        /*098*/
    { {     0x9c,0},{               0} }, { {     0x9d,0},{               0} }, { {     0x9e,0},{               0} }, { {     0x9f,0},{               0} },        /*09c*/
    { {     0xa0,0},{               0} }, { {     0xa1,0},{               0} }, { {     0xa2,0},{               0} }, { {     0xa3,0},{               0} },        /*0a0*/
    { {     0xa4,0},{               0} }, { {     0xa5,0},{               0} }, { {     0xa6,0},{               0} }, { {     0xa7,0},{               0} },        /*0a4*/
    { {     0xa8,0},{               0} }, { {     0xa9,0},{               0} }, { {     0xaa,0},{               0} }, { {     0xab,0},{               0} },        /*0a8*/
    { {     0xac,0},{               0} }, { {     0xad,0},{               0} }, { {     0xae,0},{               0} }, { {     0xaf,0},{               0} },        /*0ac*/
    { {     0xb0,0},{               0} }, { {     0xb1,0},{               0} }, { {     0xb2,0},{               0} }, { {     0xb3,0},{               0} },        /*0b0*/
    { {     0xb4,0},{               0} }, { {     0xb5,0},{               0} }, { {     0xb6,0},{               0} }, { {     0xb7,0},{               0} },        /*0b4*/
    { {     0xb8,0},{               0} }, { {     0xb9,0},{               0} }, { {     0xba,0},{               0} }, { {     0xbb,0},{               0} },        /*0b8*/
    { {     0xbc,0},{               0} }, { {     0xbd,0},{               0} }, { {     0xbe,0},{               0} }, { {     0xbf,0},{               0} },        /*0bc*/
    { {     0xc0,0},{               0} }, { {     0xc1,0},{               0} }, { {     0xc2,0},{               0} }, { {     0xc3,0},{               0} },        /*0c0*/
    { {     0xc4,0},{               0} }, { {     0xc5,0},{               0} }, { {     0xc6,0},{               0} }, { {     0xc7,0},{               0} },        /*0c4*/
    { {     0xc8,0},{               0} }, { {     0xc9,0},{               0} }, { {     0xca,0},{               0} }, { {     0xcb,0},{               0} },        /*0c8*/
    { {     0xcc,0},{               0} }, { {     0xcd,0},{               0} }, { {     0xce,0},{               0} }, { {     0xcf,0},{               0} },        /*0cc*/
    { {     0xd0,0},{               0} }, { {     0xd1,0},{               0} }, { {     0xd2,0},{               0} }, { {     0xd3,0},{               0} },        /*0d0*/
    { {     0xd4,0},{               0} }, { {     0xd5,0},{               0} }, { {     0xd6,0},{               0} }, { {     0xd7,0},{               0} },        /*0d4*/
    { {     0xd8,0},{               0} }, { {     0xd9,0},{               0} }, { {     0xda,0},{               0} }, { {     0xdb,0},{               0} },        /*0d8*/
    { {     0xdc,0},{               0} }, { {     0xdd,0},{               0} }, { {     0xde,0},{               0} }, { {     0xdf,0},{               0} },        /*0dc*/
    { {     0xe0,0},{               0} }, { {     0xe1,0},{               0} }, { {     0xe2,0},{               0} }, { {     0xe3,0},{               0} },        /*0e0*/
    { {     0xe4,0},{               0} }, { {     0xe5,0},{               0} }, { {     0xe6,0},{               0} }, { {     0xe7,0},{               0} },        /*0e4*/
    { {     0xe8,0},{               0} }, { {     0xe9,0},{               0} }, { {     0xea,0},{               0} }, { {     0xeb,0},{               0} },        /*0e8*/
    { {     0xec,0},{               0} }, { {     0xed,0},{               0} }, { {     0xee,0},{               0} }, { {     0xef,0},{               0} },        /*0ec*/
    { {          0},{               0} }, { {     0xf1,0},{               0} }, { {     0xf2,0},{               0} }, { {     0xf3,0},{               0} },        /*0f0*/
    { {     0xf4,0},{               0} }, { {     0xf5,0},{               0} }, { {     0xf6,0},{               0} }, { {     0xf7,0},{               0} },        /*0f4*/
    { {     0xf8,0},{               0} }, { {     0xf9,0},{               0} }, { {     0xfa,0},{               0} }, { {     0xfb,0},{               0} },        /*0f8*/
    { {     0xfc,0},{               0} }, { {     0xfd,0},{               0} }, { {     0xfe,0},{               0} }, { {     0xff,0},{               0} },        /*0fc*/

    { {0xe1,0x1d,0},{0xe1,     0x9d,0} }, { {0xe0,0x01,0},{0xe0,     0x81,0} }, { {0xe0,0x02,0},{0xe0,     0x82,0} }, { {0xe0,0x03,0},{0xe0,     0x83,0} },        /*100*/
    { {0xe0,0x04,0},{0xe0,     0x84,0} }, { {0xe0,0x05,0},{0xe0,     0x85,0} }, { {0xe0,0x06,0},{0xe0,     0x86,0} }, { {0xe0,0x07,0},{0xe0,     0x87,0} },        /*104*/
    { {0xe0,0x08,0},{0xe0,     0x88,0} }, { {0xe0,0x09,0},{0xe0,     0x89,0} }, { {0xe0,0x0a,0},{0xe0,     0x8a,0} }, { {0xe0,0x0b,0},{0xe0,     0x8b,0} },        /*108*/
    { {0xe0,0x0c,0},{0xe0,     0x8c,0} }, { {          0},{               0} }, { {0xe0,0x0e,0},{0xe0,     0x8e,0} }, { {0xe0,0x0f,0},{0xe0,     0x8f,0} },        /*10c*/
    { {0xe0,0x10,0},{0xe0,     0x90,0} }, { {0xe0,0x11,0},{0xe0,     0x91,0} }, { {0xe0,0x12,0},{0xe0,     0x92,0} }, { {0xe0,0x13,0},{0xe0,     0x93,0} },        /*110*/
    { {0xe0,0x14,0},{0xe0,     0x94,0} }, { {0xe0,0x15,0},{0xe0,     0x95,0} }, { {0xe0,0x16,0},{0xe0,     0x96,0} }, { {0xe0,0x17,0},{0xe0,     0x97,0} },        /*114*/
    { {0xe0,0x18,0},{0xe0,     0x98,0} }, { {0xe0,0x19,0},{0xe0,     0x99,0} }, { {0xe0,0x1a,0},{0xe0,     0x9a,0} }, { {0xe0,0x1b,0},{0xe0,     0x9b,0} },        /*118*/
    { {0xe0,0x1c,0},{0xe0,     0x9c,0} }, { {0xe0,0x1d,0},{0xe0,     0x9d,0} }, { {0xe0,0x1e,0},{0xe0,     0x9e,0} }, { {0xe0,0x1f,0},{0xe0,     0x9f,0} },        /*11c*/
    { {0xe0,0x20,0},{0xe0,     0xa0,0} }, { {0xe0,0x21,0},{0xe0,     0xa1,0} }, { {0xe0,0x22,0},{0xe0,     0xa2,0} }, { {0xe0,0x23,0},{0xe0,     0xa3,0} },        /*120*/
    { {0xe0,0x24,0},{0xe0,     0xa4,0} }, { {0xe0,0x25,0},{0xe0,     0xa5,0} }, { {0xe0,0x26,0},{0xe0,     0xa6,0} }, { {          0},{               0} },        /*124*/
    { {          0},{               0} }, { {          0},{               0} }, { {          0},{               0} }, { {          0},{               0} },        /*128*/
    { {0xe0,0x2c,0},{0xe0,     0xac,0} }, { {0xe0,0x2d,0},{0xe0,     0xad,0} }, { {0xe0,0x2e,0},{0xe0,     0xae,0} }, { {0xe0,0x2f,0},{0xe0,     0xaf,0} },        /*12c*/
    { {0xe0,0x30,0},{0xe0,     0xb0,0} }, { {0xe0,0x31,0},{0xe0,     0xb1,0} }, { {0xe0,0x32,0},{0xe0,     0xb2,0} }, { {          0},{               0} },        /*130*/
    { {0xe0,0x34,0},{0xe0,     0xb4,0} }, { {0xe0,0x35,0},{0xe0,     0xb5,0} }, { {          0},{               0} }, { {0xe0,0x37,0},{0xe0,     0xb7,0} },        /*134*/
    { {0xe0,0x38,0},{0xe0,     0xb8,0} }, { {          0},{               0} }, { {0xe0,0x3a,0},{0xe0,     0xba,0} }, { {0xe0,0x3b,0},{0xe0,     0xbb,0} },        /*138*/
    { {0xe0,0x3c,0},{0xe0,     0xbc,0} }, { {0xe0,0x3d,0},{0xe0,     0xbd,0} }, { {0xe0,0x3e,0},{0xe0,     0xbe,0} }, { {0xe0,0x3f,0},{0xe0,     0xbf,0} },        /*13c*/
    { {0xe0,0x40,0},{0xe0,     0xc0,0} }, { {0xe0,0x41,0},{0xe0,     0xc1,0} }, { {0xe0,0x42,0},{0xe0,     0xc2,0} }, { {0xe0,0x43,0},{0xe0,     0xc3,0} },        /*140*/
    { {0xe0,0x44,0},{0xe0,     0xc4,0} }, { {          0},{               0} }, { {0xe0,0x46,0},{0xe0,     0xc6,0} }, { {0xe0,0x47,0},{0xe0,     0xc7,0} },        /*144*/
    { {0xe0,0x48,0},{0xe0,     0xc8,0} }, { {0xe0,0x49,0},{0xe0,     0xc9,0} }, { {          0},{               0} }, { {0xe0,0x4b,0},{0xe0,     0xcb,0} },        /*148*/
    { {0xe0,0x4c,0},{0xe0,     0xcc,0} }, { {0xe0,0x4d,0},{0xe0,     0xcd,0} }, { {0xe0,0x4e,0},{0xe0,     0xce,0} }, { {0xe0,0x4f,0},{0xe0,     0xcf,0} },        /*14c*/
    { {0xe0,0x50,0},{0xe0,     0xd0,0} }, { {0xe0,0x51,0},{0xe0,     0xd1,0} }, { {0xe0,0x52,0},{0xe0,     0xd2,0} }, { {0xe0,0x53,0},{0xe0,     0xd3,0} },        /*150*/
    { {          0},{               0} }, { {0xe0,0x55,0},{0xe0,     0xd5,0} }, { {          0},{               0} }, { {0xe0,0x57,0},{0xe0,     0xd7,0} },        /*154*/
    { {0xe0,0x58,0},{0xe0,     0xd8,0} }, { {0xe0,0x59,0},{0xe0,     0xd9,0} }, { {0xe0,0x5a,0},{0xe0,     0xaa,0} }, { {0xe0,0x5b,0},{0xe0,     0xdb,0} },        /*158*/
    { {0xe0,0x5c,0},{0xe0,     0xdc,0} }, { {0xe0,0x5d,0},{0xe0,     0xdd,0} }, { {0xe0,0x5e,0},{0xe0,     0xee,0} }, { {0xe0,0x5f,0},{0xe0,     0xdf,0} },        /*15c*/
    { {          0},{               0} }, { {0xe0,0x61,0},{0xe0,     0xe1,0} }, { {0xe0,0x62,0},{0xe0,     0xe2,0} }, { {0xe0,0x63,0},{0xe0,     0xe3,0} },        /*160*/
    { {0xe0,0x64,0},{0xe0,     0xe4,0} }, { {0xe0,0x65,0},{0xe0,     0xe5,0} }, { {0xe0,0x66,0},{0xe0,     0xe6,0} }, { {0xe0,0x67,0},{0xe0,     0xe7,0} },        /*164*/
    { {0xe0,0x68,0},{0xe0,     0xe8,0} }, { {0xe0,0x69,0},{0xe0,     0xe9,0} }, { {0xe0,0x6a,0},{0xe0,     0xea,0} }, { {0xe0,0x6b,0},{0xe0,     0xeb,0} },        /*168*/
    { {0xe0,0x6c,0},{0xe0,     0xec,0} }, { {0xe0,0x6d,0},{0xe0,     0xed,0} }, { {0xe0,0x6e,0},{0xe0,     0xee,0} }, { {          0},{               0} },        /*16c*/
    { {0xe0,0x70,0},{0xe0,     0xf0,0} }, { {0xe0,0x71,0},{0xe0,     0xf1,0} }, { {0xe0,0x72,0},{0xe0,     0xf2,0} }, { {0xe0,0x73,0},{0xe0,     0xf3,0} },        /*170*/
    { {0xe0,0x74,0},{0xe0,     0xf4,0} }, { {0xe0,0x75,0},{0xe0,     0xf5,0} }, { {          0},{               0} }, { {0xe0,0x77,0},{0xe0,     0xf7,0} },        /*174*/
    { {0xe0,0x78,0},{0xe0,     0xf8,0} }, { {0xe0,0x79,0},{0xe0,     0xf9,0} }, { {0xe0,0x7a,0},{0xe0,     0xfa,0} }, { {0xe0,0x7b,0},{0xe0,     0xfb,0} },        /*178*/
    { {0xe0,0x7c,0},{0xe0,     0xfc,0} }, { {0xe0,0x7d,0},{0xe0,     0xfd,0} }, { {0xe0,0x7e,0},{0xe0,     0xfe,0} }, { {0xe0,0x7f,0},{0xe0,     0xff,0} },        /*17c*/

    { {          0},{               0} }, { {          0},{               0} }, { {          0},{               0} }, { {          0},{               0} },        /*180*/
    { {          0},{               0} }, { {          0},{               0} }, { {          0},{               0} }, { {          0},{               0} },        /*184*/
    { {          0},{               0} }, { {          0},{               0} }, { {          0},{               0} }, { {          0},{               0} },        /*188*/
    { {          0},{               0} }, { {          0},{               0} }, { {          0},{               0} }, { {          0},{               0} },        /*18c*/
    { {          0},{               0} }, { {          0},{               0} }, { {          0},{               0} }, { {          0},{               0} },        /*190*/
    { {          0},{               0} }, { {          0},{               0} }, { {          0},{               0} }, { {          0},{               0} },        /*194*/
    { {          0},{               0} }, { {          0},{               0} }, { {          0},{               0} }, { {          0},{               0} },        /*198*/
    { {          0},{               0} }, { {          0},{               0} }, { {          0},{               0} }, { {          0},{               0} },        /*19c*/
    { {          0},{               0} }, { {          0},{               0} }, { {          0},{               0} }, { {          0},{               0} },        /*1a0*/
    { {          0},{               0} }, { {          0},{               0} }, { {          0},{               0} }, { {          0},{               0} },        /*1a4*/
    { {          0},{               0} }, { {          0},{               0} }, { {          0},{               0} }, { {          0},{               0} },        /*1a8*/
    { {          0},{               0} }, { {          0},{               0} }, { {          0},{               0} }, { {          0},{               0} },        /*1ac*/
    { {          0},{               0} }, { {          0},{               0} }, { {          0},{               0} }, { {          0},{               0} },        /*1c0*/
    { {          0},{               0} }, { {          0},{               0} }, { {          0},{               0} }, { {          0},{               0} },        /*1c4*/
    { {          0},{               0} }, { {          0},{               0} }, { {          0},{               0} }, { {          0},{               0} },        /*1c8*/
    { {          0},{               0} }, { {          0},{               0} }, { {          0},{               0} }, { {          0},{               0} },        /*1cc*/
    { {          0},{               0} }, { {          0},{               0} }, { {          0},{               0} }, { {          0},{               0} },        /*1d0*/
    { {          0},{               0} }, { {          0},{               0} }, { {          0},{               0} }, { {          0},{               0} },        /*1d4*/
    { {          0},{               0} }, { {          0},{               0} }, { {          0},{               0} }, { {          0},{               0} },        /*1d8*/
    { {          0},{               0} }, { {          0},{               0} }, { {          0},{               0} }, { {          0},{               0} },        /*1dc*/
    { {          0},{               0} }, { {0xe0,0xe1,0},{               0} }, { {          0},{               0} }, { {          0},{               0} },        /*1e0*/
    { {          0},{               0} }, { {          0},{               0} }, { {          0},{               0} }, { {          0},{               0} },        /*1e4*/
    { {          0},{               0} }, { {          0},{               0} }, { {          0},{               0} }, { {          0},{               0} },        /*1e8*/
    { {          0},{               0} }, { {          0},{               0} }, { {0xe0,0xee,0},{               0} }, { {          0},{               0} },        /*1ec*/
    { {          0},{               0} }, { {0xe0,0xf1,0},{               0} }, { {          0},{               0} }, { {          0},{               0} },        /*1f0*/
    { {          0},{               0} }, { {          0},{               0} }, { {          0},{               0} }, { {          0},{               0} },        /*1f4*/
    { {          0},{               0} }, { {          0},{               0} }, { {          0},{               0} }, { {          0},{               0} },        /*1f8*/
    { {          0},{               0} }, { {          0},{               0} }, { {0xe0,0xfe,0},{               0} }, { {0xe0,0xff,0},{               0} }         /*1fc*/
  // clang-format on
};

static const scancode scancode_set2[512] = {
  // clang-format off
    { {          0},{               0} }, { {     0x76,0},{     0xF0,0x76,0} }, { {     0x16,0},{     0xF0,0x16,0} }, { {     0x1E,0},{     0xF0,0x1E,0} },        /*000*/
    { {     0x26,0},{     0xF0,0x26,0} }, { {     0x25,0},{     0xF0,0x25,0} }, { {     0x2E,0},{     0xF0,0x2E,0} }, { {     0x36,0},{     0xF0,0x36,0} },        /*004*/
    { {     0x3D,0},{     0xF0,0x3D,0} }, { {     0x3E,0},{     0xF0,0x3E,0} }, { {     0x46,0},{     0xF0,0x46,0} }, { {     0x45,0},{     0xF0,0x45,0} },        /*008*/
    { {     0x4E,0},{     0xF0,0x4E,0} }, { {     0x55,0},{     0xF0,0x55,0} }, { {     0x66,0},{     0xF0,0x66,0} }, { {     0x0D,0},{     0xF0,0x0D,0} },        /*00c*/
    { {     0x15,0},{     0xF0,0x15,0} }, { {     0x1D,0},{     0xF0,0x1D,0} }, { {     0x24,0},{     0xF0,0x24,0} }, { {     0x2D,0},{     0xF0,0x2D,0} },        /*010*/
    { {     0x2C,0},{     0xF0,0x2C,0} }, { {     0x35,0},{     0xF0,0x35,0} }, { {     0x3C,0},{     0xF0,0x3C,0} }, { {     0x43,0},{     0xF0,0x43,0} },        /*014*/
    { {     0x44,0},{     0xF0,0x44,0} }, { {     0x4D,0},{     0xF0,0x4D,0} }, { {     0x54,0},{     0xF0,0x54,0} }, { {     0x5B,0},{     0xF0,0x5B,0} },        /*018*/
    { {     0x5A,0},{     0xF0,0x5A,0} }, { {     0x14,0},{     0xF0,0x14,0} }, { {     0x1C,0},{     0xF0,0x1C,0} }, { {     0x1B,0},{     0xF0,0x1B,0} },        /*01c*/
    { {     0x23,0},{     0xF0,0x23,0} }, { {     0x2B,0},{     0xF0,0x2B,0} }, { {     0x34,0},{     0xF0,0x34,0} }, { {     0x33,0},{     0xF0,0x33,0} },        /*020*/
    { {     0x3B,0},{     0xF0,0x3B,0} }, { {     0x42,0},{     0xF0,0x42,0} }, { {     0x4B,0},{     0xF0,0x4B,0} }, { {     0x4C,0},{     0xF0,0x4C,0} },        /*024*/
    { {     0x52,0},{     0xF0,0x52,0} }, { {     0x0E,0},{     0xF0,0x0E,0} }, { {     0x12,0},{     0xF0,0x12,0} }, { {     0x5D,0},{     0xF0,0x5D,0} },        /*028*/
    { {     0x1A,0},{     0xF0,0x1A,0} }, { {     0x22,0},{     0xF0,0x22,0} }, { {     0x21,0},{     0xF0,0x21,0} }, { {     0x2A,0},{     0xF0,0x2A,0} },        /*02c*/
    { {     0x32,0},{     0xF0,0x32,0} }, { {     0x31,0},{     0xF0,0x31,0} }, { {     0x3A,0},{     0xF0,0x3A,0} }, { {     0x41,0},{     0xF0,0x41,0} },        /*030*/
    { {     0x49,0},{     0xF0,0x49,0} }, { {     0x4A,0},{     0xF0,0x4A,0} }, { {     0x59,0},{     0xF0,0x59,0} }, { {     0x7C,0},{     0xF0,0x7C,0} },        /*034*/
    { {     0x11,0},{     0xF0,0x11,0} }, { {     0x29,0},{     0xF0,0x29,0} }, { {     0x58,0},{     0xF0,0x58,0} }, { {     0x05,0},{     0xF0,0x05,0} },        /*038*/
    { {     0x06,0},{     0xF0,0x06,0} }, { {     0x04,0},{     0xF0,0x04,0} }, { {     0x0C,0},{     0xF0,0x0C,0} }, { {     0x03,0},{     0xF0,0x03,0} },        /*03c*/
    { {     0x0B,0},{     0xF0,0x0B,0} }, { {     0x83,0},{     0xF0,0x83,0} }, { {     0x0A,0},{     0xF0,0x0A,0} }, { {     0x01,0},{     0xF0,0x01,0} },        /*040*/
    { {     0x09,0},{     0xF0,0x09,0} }, { {     0x77,0},{     0xF0,0x77,0} }, { {     0x7E,0},{     0xF0,0x7E,0} }, { {     0x6C,0},{     0xF0,0x6C,0} },        /*044*/
    { {     0x75,0},{     0xF0,0x75,0} }, { {     0x7D,0},{     0xF0,0x7D,0} }, { {     0x7B,0},{     0xF0,0x7B,0} }, { {     0x6B,0},{     0xF0,0x6B,0} },        /*048*/
    { {     0x73,0},{     0xF0,0x73,0} }, { {     0x74,0},{     0xF0,0x74,0} }, { {     0x79,0},{     0xF0,0x79,0} }, { {     0x69,0},{     0xF0,0x69,0} },        /*04c*/
    { {     0x72,0},{     0xF0,0x72,0} }, { {     0x7A,0},{     0xF0,0x7A,0} }, { {     0x70,0},{     0xF0,0x70,0} }, { {     0x71,0},{     0xF0,0x71,0} },        /*050*/
    { {     0x84,0},{     0xF0,0x84,0} }, { {     0x60,0},{     0xF0,0x60,0} }, { {     0x61,0},{     0xF0,0x61,0} }, { {     0x78,0},{     0xF0,0x78,0} },        /*054*/
    { {     0x07,0},{     0xF0,0x07,0} }, { {     0x0F,0},{     0xF0,0x0F,0} }, { {     0x17,0},{     0xF0,0x17,0} }, { {     0x1F,0},{     0xF0,0x1F,0} },        /*058*/
    { {     0x27,0},{     0xF0,0x27,0} }, { {     0x2F,0},{     0xF0,0x2F,0} }, { {     0x37,0},{     0xF0,0x37,0} }, { {     0x3F,0},{     0xF0,0x3F,0} },        /*05c*/
    { {     0x47,0},{     0xF0,0x47,0} }, { {     0x4F,0},{     0xF0,0x4F,0} }, { {     0x56,0},{     0xF0,0x56,0} }, { {     0x5E,0},{     0xF0,0x5E,0} },        /*060*/
    { {     0x08,0},{     0xF0,0x08,0} }, { {     0x10,0},{     0xF0,0x10,0} }, { {     0x18,0},{     0xF0,0x18,0} }, { {     0x20,0},{     0xF0,0x20,0} },        /*064*/
    { {     0x28,0},{     0xF0,0x28,0} }, { {     0x30,0},{     0xF0,0x30,0} }, { {     0x38,0},{     0xF0,0x38,0} }, { {     0x40,0},{     0xF0,0x40,0} },        /*068*/
    { {     0x48,0},{     0xF0,0x48,0} }, { {     0x50,0},{     0xF0,0x50,0} }, { {     0x57,0},{     0xF0,0x57,0} }, { {     0x6F,0},{     0xF0,0x6F,0} },        /*06c*/
    { {     0x13,0},{     0xF0,0x13,0} }, { {     0x19,0},{     0xF0,0x19,0} }, { {     0x39,0},{     0xF0,0x39,0} }, { {     0x51,0},{     0xF0,0x51,0} },        /*070*/
    { {     0x53,0},{     0xF0,0x53,0} }, { {     0x5C,0},{     0xF0,0x5C,0} }, { {     0x5F,0},{     0xF0,0x5F,0} }, { {     0x62,0},{     0xF0,0x62,0} },        /*074*/
    { {     0x63,0},{     0xF0,0x63,0} }, { {     0x64,0},{     0xF0,0x64,0} }, { {     0x65,0},{     0xF0,0x65,0} }, { {     0x67,0},{     0xF0,0x67,0} },        /*078*/
    { {     0x68,0},{     0xF0,0x68,0} }, { {     0x6A,0},{     0xF0,0x6A,0} }, { {     0x6D,0},{     0xF0,0x6D,0} }, { {     0x6E,0},{     0xF0,0x6E,0} },        /*07c*/

    { {     0x80,0},{     0xf0,0x80,0} }, { {     0x81,0},{     0xf0,0x81,0} }, { {     0x82,0},{     0xf0,0x82,0} }, { {          0},{               0} },        /*080*/
    { {          0},{               0} }, { {     0x85,0},{     0xf0,0x54,0} }, { {     0x86,0},{     0xf0,0x86,0} }, { {     0x87,0},{     0xf0,0x87,0} },        /*084*/
    { {     0x88,0},{     0xf0,0x88,0} }, { {     0x89,0},{     0xf0,0x89,0} }, { {     0x8a,0},{     0xf0,0x8a,0} }, { {     0x8b,0},{     0xf0,0x8b,0} },        /*088*/
    { {     0x8c,0},{     0xf0,0x8c,0} }, { {     0x8d,0},{     0xf0,0x8d,0} }, { {     0x8e,0},{     0xf0,0x8e,0} }, { {     0x8f,0},{     0xf0,0x8f,0} },        /*08c*/
    { {     0x90,0},{     0xf0,0x90,0} }, { {     0x91,0},{     0xf0,0x91,0} }, { {     0x92,0},{     0xf0,0x92,0} }, { {     0x93,0},{     0xf0,0x93,0} },        /*090*/
    { {     0x94,0},{     0xf0,0x94,0} }, { {     0x95,0},{     0xf0,0x95,0} }, { {     0x96,0},{     0xf0,0x96,0} }, { {     0x97,0},{     0xf0,0x97,0} },        /*094*/
    { {     0x98,0},{     0xf0,0x98,0} }, { {     0x99,0},{     0xf0,0x99,0} }, { {     0x9a,0},{     0xf0,0x9a,0} }, { {     0x9b,0},{     0xf0,0x9b,0} },        /*098*/
    { {     0x9c,0},{     0xf0,0x9c,0} }, { {     0x9d,0},{     0xf0,0x9d,0} }, { {     0x9e,0},{     0xf0,0x9e,0} }, { {     0x9f,0},{     0xf0,0x9f,0} },        /*09c*/
    { {     0xa0,0},{     0xf0,0xa0,0} }, { {     0xa1,0},{     0xf0,0xa1,0} }, { {     0xa2,0},{     0xf0,0xa2,0} }, { {     0xa3,0},{     0xf0,0xa3,0} },        /*0a0*/
    { {     0xa4,0},{     0xf0,0xa4,0} }, { {     0xa5,0},{     0xf0,0xa5,0} }, { {     0xa6,0},{     0xf0,0xa6,0} }, { {     0xa7,0},{     0xf0,0xa7,0} },        /*0a4*/
    { {     0xa8,0},{     0xf0,0xa8,0} }, { {     0xa9,0},{     0xf0,0xa9,0} }, { {     0xaa,0},{     0xf0,0xaa,0} }, { {     0xab,0},{     0xf0,0xab,0} },        /*0a8*/
    { {     0xac,0},{     0xf0,0xac,0} }, { {     0xad,0},{     0xf0,0xad,0} }, { {     0xae,0},{     0xf0,0xae,0} }, { {     0xaf,0},{     0xf0,0xaf,0} },        /*0ac*/
    { {     0xb0,0},{     0xf0,0xb0,0} }, { {     0xb1,0},{     0xf0,0xb1,0} }, { {     0xb2,0},{     0xf0,0xb2,0} }, { {     0xb3,0},{     0xf0,0xb3,0} },        /*0b0*/
    { {     0xb4,0},{     0xf0,0xb4,0} }, { {     0xb5,0},{     0xf0,0xb5,0} }, { {     0xb6,0},{     0xf0,0xb6,0} }, { {     0xb7,0},{     0xf0,0xb7,0} },        /*0b4*/
    { {     0xb8,0},{     0xf0,0xb8,0} }, { {     0xb9,0},{     0xf0,0xb9,0} }, { {     0xba,0},{     0xf0,0xba,0} }, { {     0xbb,0},{     0xf0,0xbb,0} },        /*0b8*/
    { {     0xbc,0},{     0xf0,0xbc,0} }, { {     0xbd,0},{     0xf0,0xbd,0} }, { {     0xbe,0},{     0xf0,0xbe,0} }, { {     0xbf,0},{     0xf0,0xbf,0} },        /*0bc*/
    { {     0xc0,0},{     0xf0,0xc0,0} }, { {     0xc1,0},{     0xf0,0xc1,0} }, { {     0xc2,0},{     0xf0,0xc2,0} }, { {     0xc3,0},{     0xf0,0xc3,0} },        /*0c0*/
    { {     0xc4,0},{     0xf0,0xc4,0} }, { {     0xc5,0},{     0xf0,0xc5,0} }, { {     0xc6,0},{     0xf0,0xc6,0} }, { {     0xc7,0},{     0xf0,0xc7,0} },        /*0c4*/
    { {     0xc8,0},{     0xf0,0xc8,0} }, { {     0xc9,0},{     0xf0,0xc9,0} }, { {     0xca,0},{     0xf0,0xca,0} }, { {     0xcb,0},{     0xf0,0xcb,0} },        /*0c8*/
    { {     0xcc,0},{     0xf0,0xcc,0} }, { {     0xcd,0},{     0xf0,0xcd,0} }, { {     0xce,0},{     0xf0,0xce,0} }, { {     0xcf,0},{     0xf0,0xcf,0} },        /*0cc*/
    { {     0xd0,0},{     0xf0,0xd0,0} }, { {     0xd1,0},{     0xf0,0xd0,0} }, { {     0xd2,0},{     0xf0,0xd2,0} }, { {     0xd3,0},{     0xf0,0xd3,0} },        /*0d0*/
    { {     0xd4,0},{     0xf0,0xd4,0} }, { {     0xd5,0},{     0xf0,0xd5,0} }, { {     0xd6,0},{     0xf0,0xd6,0} }, { {     0xd7,0},{     0xf0,0xd7,0} },        /*0d4*/
    { {     0xd8,0},{     0xf0,0xd8,0} }, { {     0xd9,0},{     0xf0,0xd9,0} }, { {     0xda,0},{     0xf0,0xda,0} }, { {     0xdb,0},{     0xf0,0xdb,0} },        /*0d8*/
    { {     0xdc,0},{     0xf0,0xdc,0} }, { {     0xdd,0},{     0xf0,0xdd,0} }, { {     0xde,0},{     0xf0,0xde,0} }, { {     0xdf,0},{     0xf0,0xdf,0} },        /*0dc*/
    { {     0xe0,0},{     0xf0,0xe0,0} }, { {     0xe1,0},{     0xf0,0xe1,0} }, { {     0xe2,0},{     0xf0,0xe2,0} }, { {     0xe3,0},{     0xf0,0xe3,0} },        /*0e0*/
    { {     0xe4,0},{     0xf0,0xe4,0} }, { {     0xe5,0},{     0xf0,0xe5,0} }, { {     0xe6,0},{     0xf0,0xe6,0} }, { {     0xe7,0},{     0xf0,0xe7,0} },        /*0e4*/
    { {     0xe8,0},{     0xf0,0xe8,0} }, { {     0xe9,0},{     0xf0,0xe9,0} }, { {     0xea,0},{     0xf0,0xea,0} }, { {     0xeb,0},{     0xf0,0xeb,0} },        /*0e8*/
    { {     0xec,0},{     0xf0,0xec,0} }, { {     0xed,0},{     0xf0,0xed,0} }, { {     0xee,0},{     0xf0,0xee,0} }, { {     0xef,0},{     0xf0,0xef,0} },        /*0ec*/
    { {          0},{               0} }, { {     0xf1,0},{     0xf0,0xf1,0} }, { {     0xf2,0},{     0xf0,0xf2,0} }, { {     0xf3,0},{     0xf0,0xf3,0} },        /*0f0*/
    { {     0xf4,0},{     0xf0,0xf4,0} }, { {     0xf5,0},{     0xf0,0xf5,0} }, { {     0xf6,0},{     0xf0,0xf6,0} }, { {     0xf7,0},{     0xf0,0xf7,0} },        /*0f4*/
    { {     0xf8,0},{     0xf0,0xf8,0} }, { {     0xf9,0},{     0xf0,0xf9,0} }, { {     0xfa,0},{     0xf0,0xfa,0} }, { {     0xfb,0},{     0xf0,0xfb,0} },        /*0f8*/
    { {     0xfc,0},{     0xf0,0xfc,0} }, { {     0xfd,0},{     0xf0,0xfd,0} }, { {     0xfe,0},{     0xf0,0xfe,0} }, { {     0xff,0},{     0xf0,0xff,0} },        /*0fc*/

    { {0xe1,0x14,0},{0xe1,0xf0,0x14,0} }, { {0xe0,0x76,0},{0xe0,0xF0,0x76,0} }, { {0xe0,0x16,0},{0xe0,0xF0,0x16,0} }, { {0xe0,0x1E,0},{0xe0,0xF0,0x1E,0} },        /*100*/
    { {0xe0,0x26,0},{0xe0,0xF0,0x26,0} }, { {0xe0,0x25,0},{0xe0,0xF0,0x25,0} }, { {0xe0,0x2E,0},{0xe0,0xF0,0x2E,0} }, { {0xe0,0x36,0},{0xe0,0xF0,0x36,0} },        /*104*/
    { {0xe0,0x3D,0},{0xe0,0xF0,0x3D,0} }, { {0xe0,0x3E,0},{0xe0,0xF0,0x3E,0} }, { {0xe0,0x46,0},{0xe0,0xF0,0x46,0} }, { {0xe0,0x45,0},{0xe0,0xF0,0x45,0} },        /*108*/
    { {0xe0,0x4E,0},{0xe0,0xF0,0x4E,0} }, { {          0},{               0} }, { {0xe0,0x66,0},{0xe0,0xF0,0x66,0} }, { {0xe0,0x0D,0},{0xe0,0xF0,0x0D,0} },        /*10c*/
    { {0xe0,0x15,0},{0xe0,0xF0,0x15,0} }, { {0xe0,0x1D,0},{0xe0,0xF0,0x1D,0} }, { {0xe0,0x24,0},{0xe0,0xF0,0x24,0} }, { {0xe0,0x2D,0},{0xe0,0xF0,0x2D,0} },        /*110*/
    { {0xe0,0x2C,0},{0xe0,0xF0,0x2C,0} }, { {0xe0,0x35,0},{0xe0,0xF0,0x35,0} }, { {0xe0,0x3C,0},{0xe0,0xF0,0x3C,0} }, { {0xe0,0x43,0},{0xe0,0xF0,0x43,0} },        /*114*/
    { {0xe0,0x44,0},{0xe0,0xF0,0x44,0} }, { {0xe0,0x4D,0},{0xe0,0xF0,0x4D,0} }, { {0xe0,0x54,0},{0xe0,0xF0,0x54,0} }, { {0xe0,0x5B,0},{0xe0,0xF0,0x5B,0} },        /*118*/
    { {0xe0,0x5A,0},{0xe0,0xF0,0x5A,0} }, { {0xe0,0x14,0},{0xe0,0xF0,0x14,0} }, { {0xe0,0x1C,0},{0xe0,0xF0,0x1C,0} }, { {0xe0,0x1B,0},{0xe0,0xF0,0x1B,0} },        /*11c*/
    { {0xe0,0x23,0},{0xe0,0xF0,0x23,0} }, { {0xe0,0x2B,0},{0xe0,0xF0,0x2B,0} }, { {0xe0,0x34,0},{0xe0,0xF0,0x34,0} }, { {0xe0,0x33,0},{0xe0,0xF0,0x33,0} },        /*120*/
    { {0xe0,0x3B,0},{0xe0,0xF0,0x3B,0} }, { {0xe0,0x42,0},{0xe0,0xF0,0x42,0} }, { {0xe0,0x4B,0},{0xe0,0xF0,0x4B,0} }, { {          0},{               0} },        /*124*/
    { {          0},{               0} }, { {          0},{               0} }, { {          0},{               0} }, { {          0},{               0} },        /*128*/
    { {0xe0,0x1A,0},{0xe0,0xF0,0x1A,0} }, { {0xe0,0x22,0},{0xe0,0xF0,0x22,0} }, { {0xe0,0x21,0},{0xe0,0xF0,0x21,0} }, { {0xe0,0x2A,0},{0xe0,0xF0,0x2A,0} },        /*12c*/
    { {0xe0,0x32,0},{0xe0,0xF0,0x32,0} }, { {0xe0,0x31,0},{0xe0,0xF0,0x31,0} }, { {0xe0,0x3A,0},{0xe0,0xF0,0x3A,0} }, { {          0},{               0} },        /*130*/
    { {0xe0,0x49,0},{0xe0,0xF0,0x49,0} }, { {0xe0,0x4A,0},{0xe0,0xF0,0x4A,0} }, { {          0},{               0} }, { {0xe0,0x7C,0},{0xe0,0xF0,0x7C,0} },        /*134*/
    { {0xe0,0x11,0},{0xe0,0xF0,0x11,0} }, { {          0},{               0} }, { {0xe0,0x58,0},{0xe0,0xF0,0x58,0} }, { {0xe0,0x05,0},{0xe0,0xF0,0x05,0} },        /*138*/
    { {0xe0,0x06,0},{0xe0,0xF0,0x06,0} }, { {0xe0,0x04,0},{0xe0,0xF0,0x04,0} }, { {0xe0,0x0C,0},{0xe0,0xF0,0x0C,0} }, { {0xe0,0x03,0},{0xe0,0xF0,0x03,0} },        /*13c*/
    { {0xe0,0x0B,0},{0xe0,0xF0,0x0B,0} }, { {0xe0,0x02,0},{0xe0,0xF0,0x02,0} }, { {0xe0,0x0A,0},{0xe0,0xF0,0x0A,0} }, { {0xe0,0x01,0},{0xe0,0xF0,0x01,0} },        /*140*/
    { {0xe0,0x09,0},{0xe0,0xF0,0x09,0} }, { {          0},{               0} }, { {0xe0,0x7E,0},{0xe0,0xF0,0x7E,0} }, { {0xe0,0x6C,0},{0xe0,0xF0,0x6C,0} },        /*144*/
    { {0xe0,0x75,0},{0xe0,0xF0,0x75,0} }, { {0xe0,0x7D,0},{0xe0,0xF0,0x7D,0} }, { {          0},{               0} }, { {0xe0,0x6B,0},{0xe0,0xF0,0x6B,0} },        /*148*/
    { {0xe0,0x73,0},{0xe0,0xF0,0x73,0} }, { {0xe0,0x74,0},{0xe0,0xF0,0x74,0} }, { {0xe0,0x79,0},{0xe0,0xF0,0x79,0} }, { {0xe0,0x69,0},{0xe0,0xF0,0x69,0} },        /*14c*/
    { {0xe0,0x72,0},{0xe0,0xF0,0x72,0} }, { {0xe0,0x7A,0},{0xe0,0xF0,0x7A,0} }, { {0xe0,0x70,0},{0xe0,0xF0,0x70,0} }, { {0xe0,0x71,0},{0xe0,0xF0,0x71,0} },        /*150*/
    { {          0},{               0} }, { {0xe0,0x60,0},{0xe0,0xF0,0x60,0} }, { {          0},{               0} }, { {0xe0,0x78,0},{0xe0,0xF0,0x78,0} },        /*154*/
    { {0xe0,0x07,0},{0xe0,0xF0,0x07,0} }, { {0xe0,0x0F,0},{0xe0,0xF0,0x0F,0} }, { {0xe0,0x17,0},{0xe0,0xF0,0x17,0} }, { {0xe0,0x1F,0},{0xe0,0xF0,0x1F,0} },        /*158*/
    { {0xe0,0x27,0},{0xe0,0xF0,0x27,0} }, { {0xe0,0x2F,0},{0xe0,0xF0,0x2F,0} }, { {0xe0,0x37,0},{0xe0,0xF0,0x37,0} }, { {0xe0,0x3F,0},{0xe0,0xF0,0x3F,0} },        /*15c*/
    { {          0},{               0} }, { {0xe0,0x4F,0},{0xe0,0xF0,0x4F,0} }, { {0xe0,0x56,0},{0xe0,0xF0,0x56,0} }, { {0xe0,0x5E,0},{0xe0,0xF0,0x5E,0} },        /*160*/
    { {0xe0,0x08,0},{0xe0,0xF0,0x08,0} }, { {0xe0,0x10,0},{0xe0,0xF0,0x10,0} }, { {0xe0,0x18,0},{0xe0,0xF0,0x18,0} }, { {0xe0,0x20,0},{0xe0,0xF0,0x20,0} },        /*164*/
    { {0xe0,0x28,0},{0xe0,0xF0,0x28,0} }, { {0xe0,0x30,0},{0xe0,0xF0,0x30,0} }, { {0xe0,0x38,0},{0xe0,0xF0,0x38,0} }, { {0xe0,0x40,0},{0xe0,0xF0,0x40,0} },        /*168*/
    { {0xe0,0x48,0},{0xe0,0xF0,0x48,0} }, { {0xe0,0x50,0},{0xe0,0xF0,0x50,0} }, { {0xe0,0x57,0},{0xe0,0xF0,0x57,0} }, { {          0},{               0} },        /*16c*/
    { {0xe0,0x13,0},{0xe0,0xF0,0x13,0} }, { {0xe0,0x19,0},{0xe0,0xF0,0x19,0} }, { {0xe0,0x39,0},{0xe0,0xF0,0x39,0} }, { {0xe0,0x51,0},{0xe0,0xF0,0x51,0} },        /*170*/
    { {0xe0,0x53,0},{0xe0,0xF0,0x53,0} }, { {0xe0,0x5C,0},{0xe0,0xF0,0x5C,0} }, { {          0},{               0} }, { {0xe0,0x62,0},{0xe0,0xF0,0x62,0} },        /*174*/
    { {0xe0,0x63,0},{0xe0,0xF0,0x63,0} }, { {0xe0,0x64,0},{0xe0,0xF0,0x64,0} }, { {0xe0,0x65,0},{0xe0,0xF0,0x65,0} }, { {0xe0,0x67,0},{0xe0,0xF0,0x67,0} },        /*178*/
    { {0xe0,0x68,0},{0xe0,0xF0,0x68,0} }, { {0xe0,0x6A,0},{0xe0,0xF0,0x6A,0} }, { {0xe0,0x6D,0},{0xe0,0xF0,0x6D,0} }, { {0xe0,0x6E,0},{0xe0,0xF0,0x6E,0} },        /*17c*/

    { {          0},{               0} }, { {          0},{               0} }, { {          0},{               0} }, { {          0},{               0} },        /*180*/
    { {          0},{               0} }, { {          0},{               0} }, { {          0},{               0} }, { {          0},{               0} },        /*184*/
    { {          0},{               0} }, { {          0},{               0} }, { {          0},{               0} }, { {          0},{               0} },        /*188*/
    { {          0},{               0} }, { {          0},{               0} }, { {          0},{               0} }, { {          0},{               0} },        /*18c*/
    { {          0},{               0} }, { {          0},{               0} }, { {          0},{               0} }, { {          0},{               0} },        /*190*/
    { {          0},{               0} }, { {          0},{               0} }, { {          0},{               0} }, { {          0},{               0} },        /*194*/
    { {          0},{               0} }, { {          0},{               0} }, { {          0},{               0} }, { {          0},{               0} },        /*198*/
    { {          0},{               0} }, { {          0},{               0} }, { {          0},{               0} }, { {          0},{               0} },        /*19c*/
    { {          0},{               0} }, { {          0},{               0} }, { {          0},{               0} }, { {          0},{               0} },        /*1a0*/
    { {          0},{               0} }, { {          0},{               0} }, { {          0},{               0} }, { {          0},{               0} },        /*1a4*/
    { {          0},{               0} }, { {          0},{               0} }, { {          0},{               0} }, { {          0},{               0} },        /*1a8*/
    { {          0},{               0} }, { {          0},{               0} }, { {          0},{               0} }, { {          0},{               0} },        /*1ac*/
    { {          0},{               0} }, { {          0},{               0} }, { {          0},{               0} }, { {          0},{               0} },        /*1c0*/
    { {          0},{               0} }, { {          0},{               0} }, { {          0},{               0} }, { {          0},{               0} },        /*1c4*/
    { {          0},{               0} }, { {          0},{               0} }, { {          0},{               0} }, { {          0},{               0} },        /*1c8*/
    { {          0},{               0} }, { {          0},{               0} }, { {          0},{               0} }, { {          0},{               0} },        /*1cc*/
    { {          0},{               0} }, { {          0},{               0} }, { {          0},{               0} }, { {          0},{               0} },        /*1d0*/
    { {          0},{               0} }, { {          0},{               0} }, { {          0},{               0} }, { {          0},{               0} },        /*1d4*/
    { {          0},{               0} }, { {          0},{               0} }, { {          0},{               0} }, { {          0},{               0} },        /*1d8*/
    { {          0},{               0} }, { {          0},{               0} }, { {          0},{               0} }, { {          0},{               0} },        /*1dc*/
    { {          0},{               0} }, { {0xe0,0xe1,0},{0xe0,0xF0,0xE1,0} }, { {          0},{               0} }, { {          0},{               0} },        /*1e0*/
    { {          0},{               0} }, { {          0},{               0} }, { {          0},{               0} }, { {          0},{               0} },        /*1e4*/
    { {          0},{               0} }, { {          0},{               0} }, { {          0},{               0} }, { {          0},{               0} },        /*1e8*/
    { {          0},{               0} }, { {          0},{               0} }, { {0xe0,0xee,0},{0xe0,0xF0,0xEE,0} }, { {          0},{               0} },        /*1ec*/
    { {          0},{               0} }, { {0xe0,0xf1,0},{0xe0,0xF0,0xF1,0} }, { {          0},{               0} }, { {          0},{               0} },        /*1f0*/
    { {          0},{               0} }, { {          0},{               0} }, { {          0},{               0} }, { {          0},{               0} },        /*1f4*/
    { {          0},{               0} }, { {          0},{               0} }, { {          0},{               0} }, { {          0},{               0} },        /*1f8*/
    { {          0},{               0} }, { {          0},{               0} }, { {0xe0,0xfe,0},{0xe0,0xF0,0xFE,0} }, { {0xe0,0xff,0},{0xe0,0xF0,0xFF,0} }         /*1fc*/
  // clang-format on
};

static const scancode scancode_set3[512] = {
  // clang-format off
    { {          0},{               0} }, { {     0x08,0},{     0xf0,0x08,0} }, { {     0x16,0},{     0xf0,0x16,0} }, { {     0x1E,0},{     0xf0,0x1E,0} },        /*000*/
    { {     0x26,0},{     0xf0,0x26,0} }, { {     0x25,0},{     0xf0,0x25,0} }, { {     0x2E,0},{     0xf0,0x2E,0} }, { {     0x36,0},{     0xf0,0x36,0} },        /*004*/
    { {     0x3D,0},{     0xf0,0x3D,0} }, { {     0x3E,0},{     0xf0,0x3E,0} }, { {     0x46,0},{     0xf0,0x46,0} }, { {     0x45,0},{     0xf0,0x45,0} },        /*008*/
    { {     0x4E,0},{     0xf0,0x4E,0} }, { {     0x55,0},{     0xf0,0x55,0} }, { {     0x66,0},{     0xf0,0x66,0} }, { {     0x0D,0},{     0xf0,0x0D,0} },        /*00c*/
    { {     0x15,0},{     0xf0,0x15,0} }, { {     0x1D,0},{     0xf0,0x1D,0} }, { {     0x24,0},{     0xf0,0x24,0} }, { {     0x2D,0},{     0xf0,0x2D,0} },        /*010*/
    { {     0x2C,0},{     0xf0,0x2C,0} }, { {     0x35,0},{     0xf0,0x35,0} }, { {     0x3C,0},{     0xf0,0x3C,0} }, { {     0x43,0},{     0xf0,0x43,0} },        /*014*/
    { {     0x44,0},{     0xf0,0x44,0} }, { {     0x4D,0},{     0xf0,0x4D,0} }, { {     0x54,0},{     0xf0,0x54,0} }, { {     0x5B,0},{     0xf0,0x5B,0} },        /*018*/
    { {     0x5A,0},{     0xf0,0x5A,0} }, { {     0x11,0},{     0xf0,0x11,0} }, { {     0x1C,0},{     0xf0,0x1C,0} }, { {     0x1B,0},{     0xf0,0x1B,0} },        /*01c*/
    { {     0x23,0},{     0xf0,0x23,0} }, { {     0x2B,0},{     0xf0,0x2B,0} }, { {     0x34,0},{     0xf0,0x34,0} }, { {     0x33,0},{     0xf0,0x33,0} },        /*020*/
    { {     0x3B,0},{     0xf0,0x3B,0} }, { {     0x42,0},{     0xf0,0x42,0} }, { {     0x4B,0},{     0xf0,0x4B,0} }, { {     0x4C,0},{     0xf0,0x4C,0} },        /*024*/
    { {     0x52,0},{     0xf0,0x52,0} }, { {     0x0E,0},{     0xf0,0x0E,0} }, { {     0x12,0},{     0xf0,0x12,0} }, { {     0x5C,0},{     0xf0,0x5C,0} },        /*028*/
    { {     0x1A,0},{     0xf0,0x1A,0} }, { {     0x22,0},{     0xf0,0x22,0} }, { {     0x21,0},{     0xf0,0x21,0} }, { {     0x2A,0},{     0xf0,0x2A,0} },        /*02c*/
    { {     0x32,0},{     0xf0,0x32,0} }, { {     0x31,0},{     0xf0,0x31,0} }, { {     0x3A,0},{     0xf0,0x3A,0} }, { {     0x41,0},{     0xf0,0x41,0} },        /*030*/
    { {     0x49,0},{     0xf0,0x49,0} }, { {     0x4A,0},{     0xf0,0x4A,0} }, { {     0x59,0},{     0xf0,0x59,0} }, { {     0x7E,0},{     0xf0,0x7E,0} },        /*034*/
    { {     0x19,0},{     0xf0,0x19,0} }, { {     0x29,0},{     0xf0,0x29,0} }, { {     0x14,0},{     0xf0,0x14,0} }, { {     0x07,0},{     0xf0,0x07,0} },        /*038*/
    { {     0x0F,0},{     0xf0,0x0F,0} }, { {     0x17,0},{     0xf0,0x17,0} }, { {     0x1F,0},{     0xf0,0x1F,0} }, { {     0x27,0},{     0xf0,0x27,0} },        /*03c*/
    { {     0x2F,0},{     0xf0,0x2F,0} }, { {     0x37,0},{     0xf0,0x37,0} }, { {     0x3F,0},{     0xf0,0x3F,0} }, { {     0x47,0},{     0xf0,0x47,0} },        /*040*/
    { {     0x4F,0},{     0xf0,0x4F,0} }, { {     0x76,0},{     0xf0,0x76,0} }, { {     0x5F,0},{     0xf0,0x5F,0} }, { {     0x6C,0},{     0xf0,0x6C,0} },        /*044*/
    { {     0x75,0},{     0xf0,0x75,0} }, { {     0x7D,0},{     0xf0,0x7D,0} }, { {     0x84,0},{     0xf0,0x84,0} }, { {     0x6B,0},{     0xf0,0x6B,0} },        /*048*/
    { {     0x73,0},{     0xf0,0x73,0} }, { {     0x74,0},{     0xf0,0x74,0} }, { {     0x7C,0},{     0xf0,0x7C,0} }, { {     0x69,0},{     0xf0,0x69,0} },        /*04c*/
    { {     0x72,0},{     0xf0,0x72,0} }, { {     0x7A,0},{     0xf0,0x7A,0} }, { {     0x70,0},{     0xf0,0x70,0} }, { {     0x71,0},{     0xf0,0x71,0} },        /*050*/
    { {     0x57,0},{     0xf0,0x57,0} }, { {     0x60,0},{     0xf0,0x60,0} }, { {          0},{               0} }, { {     0x56,0},{     0xf0,0x56,0} },        /*054*/
    { {     0x5E,0},{     0xf0,0x5E,0} }, { {          0},{               0} }, { {          0},{               0} }, { {          0},{               0} },        /*058*/
    { {          0},{               0} }, { {          0},{               0} }, { {          0},{               0} }, { {          0},{               0} },        /*05c*/
    { {          0},{               0} }, { {          0},{               0} }, { {          0},{               0} }, { {          0},{               0} },        /*060*/
    { {          0},{               0} }, { {     0x10,0},{     0xf0,0x10,0} }, { {     0x18,0},{     0xf0,0x18,0} }, { {     0x20,0},{     0xf0,0x20,0} },        /*064*/
    { {     0x28,0},{     0xf0,0x28,0} }, { {     0x30,0},{     0xf0,0x30,0} }, { {     0x38,0},{     0xf0,0x38,0} }, { {     0x40,0},{     0xf0,0x40,0} },        /*068*/
    { {     0x48,0},{     0xf0,0x48,0} }, { {     0x50,0},{     0xf0,0x50,0} }, { {          0},{               0} }, { {          0},{               0} },        /*06c*/
    { {     0x87,0},{     0xf0,0x87,0} }, { {          0},{               0} }, { {          0},{               0} }, { {     0x51,0},{     0xf0,0x51,0} },        /*070*/
    { {     0x53,0},{     0xf0,0x53,0} }, { {     0x5C,0},{     0xf0,0x5C,0} }, { {          0},{               0} }, { {     0x62,0},{     0xf0,0x62,0} },        /*074*/
    { {     0x63,0},{     0xf0,0x63,0} }, { {     0x86,0},{     0xf0,0x86,0} }, { {          0},{               0} }, { {     0x85,0},{     0xf0,0x85,0} },        /*078*/
    { {     0x68,0},{     0xf0,0x68,0} }, { {     0x13,0},{     0xf0,0x13,0} }, { {          0},{               0} }, { {          0},{               0} },        /*07c*/

    { {     0x80,0},{     0xf0,0x80,0} }, { {     0x81,0},{     0xf0,0x81,0} }, { {     0x82,0},{     0xf0,0x82,0} }, { {          0},{               0} },        /*080*/
    { {          0},{               0} }, { {     0x85,0},{     0xf0,0x54,0} }, { {     0x86,0},{     0xf0,0x86,0} }, { {     0x87,0},{     0xf0,0x87,0} },        /*084*/
    { {     0x88,0},{     0xf0,0x88,0} }, { {     0x89,0},{     0xf0,0x89,0} }, { {     0x8a,0},{     0xf0,0x8a,0} }, { {     0x8b,0},{     0xf0,0x8b,0} },        /*088*/
    { {          0},{               0} }, { {          0},{               0} }, { {     0x8e,0},{     0xf0,0x8e,0} }, { {     0x8f,0},{     0xf0,0x8f,0} },        /*08c*/
    { {     0x90,0},{     0xf0,0x90,0} }, { {     0x91,0},{     0xf0,0x91,0} }, { {     0x92,0},{     0xf0,0x92,0} }, { {     0x93,0},{     0xf0,0x93,0} },        /*090*/
    { {     0x94,0},{     0xf0,0x94,0} }, { {     0x95,0},{     0xf0,0x95,0} }, { {     0x96,0},{     0xf0,0x96,0} }, { {     0x97,0},{     0xf0,0x97,0} },        /*094*/
    { {     0x98,0},{     0xf0,0x98,0} }, { {     0x99,0},{     0xf0,0x99,0} }, { {     0x9a,0},{     0xf0,0x9a,0} }, { {     0x9b,0},{     0xf0,0x9b,0} },        /*098*/
    { {     0x9c,0},{     0xf0,0x9c,0} }, { {     0x9d,0},{     0xf0,0x9d,0} }, { {     0x9e,0},{     0xf0,0x9e,0} }, { {     0x9f,0},{     0xf0,0x9f,0} },        /*09c*/
    { {     0xa0,0},{     0xf0,0xa0,0} }, { {     0xa1,0},{     0xf0,0xa1,0} }, { {     0xa2,0},{     0xf0,0xa2,0} }, { {     0xa3,0},{     0xf0,0xa3,0} },        /*0a0*/
    { {     0xa4,0},{     0xf0,0xa4,0} }, { {     0xa5,0},{     0xf0,0xa5,0} }, { {     0xa6,0},{     0xf0,0xa6,0} }, { {     0xa7,0},{     0xf0,0xa7,0} },        /*0a4*/
    { {     0xa8,0},{     0xf0,0xa8,0} }, { {     0xa9,0},{     0xf0,0xa9,0} }, { {     0xaa,0},{     0xf0,0xaa,0} }, { {     0xab,0},{     0xf0,0xab,0} },        /*0a8*/
    { {     0xac,0},{     0xf0,0xac,0} }, { {     0xad,0},{     0xf0,0xad,0} }, { {     0xae,0},{     0xf0,0xae,0} }, { {     0xaf,0},{     0xf0,0xaf,0} },        /*0ac*/
    { {     0xb0,0},{     0xf0,0xb0,0} }, { {     0xb1,0},{     0xf0,0xb1,0} }, { {     0xb2,0},{     0xf0,0xb2,0} }, { {     0xb3,0},{     0xf0,0xb3,0} },        /*0b0*/
    { {     0xb4,0},{     0xf0,0xb4,0} }, { {     0xb5,0},{     0xf0,0xb5,0} }, { {     0xb6,0},{     0xf0,0xb6,0} }, { {     0xb7,0},{     0xf0,0xb7,0} },        /*0b4*/
    { {     0xb8,0},{     0xf0,0xb8,0} }, { {     0xb9,0},{     0xf0,0xb9,0} }, { {     0xba,0},{     0xf0,0xba,0} }, { {     0xbb,0},{     0xf0,0xbb,0} },        /*0b8*/
    { {     0xbc,0},{     0xf0,0xbc,0} }, { {     0xbd,0},{     0xf0,0xbd,0} }, { {     0xbe,0},{     0xf0,0xbe,0} }, { {     0xbf,0},{     0xf0,0xbf,0} },        /*0bc*/
    { {     0xc0,0},{     0xf0,0xc0,0} }, { {     0xc1,0},{     0xf0,0xc1,0} }, { {     0xc2,0},{     0xf0,0xc2,0} }, { {     0xc3,0},{     0xf0,0xc3,0} },        /*0c0*/
    { {     0xc4,0},{     0xf0,0xc4,0} }, { {     0xc5,0},{     0xf0,0xc5,0} }, { {     0xc6,0},{     0xf0,0xc6,0} }, { {     0xc7,0},{     0xf0,0xc7,0} },        /*0c4*/
    { {     0xc8,0},{     0xf0,0xc8,0} }, { {     0xc9,0},{     0xf0,0xc9,0} }, { {     0xca,0},{     0xf0,0xca,0} }, { {     0xcb,0},{     0xf0,0xcb,0} },        /*0c8*/
    { {     0xcc,0},{     0xf0,0xcc,0} }, { {     0xcd,0},{     0xf0,0xcd,0} }, { {     0xce,0},{     0xf0,0xce,0} }, { {     0xcf,0},{     0xf0,0xcf,0} },        /*0cc*/
    { {     0xd0,0},{     0xf0,0xd0,0} }, { {     0xd1,0},{     0xf0,0xd0,0} }, { {     0xd2,0},{     0xf0,0xd2,0} }, { {     0xd3,0},{     0xf0,0xd3,0} },        /*0d0*/
    { {     0xd4,0},{     0xf0,0xd4,0} }, { {     0xd5,0},{     0xf0,0xd5,0} }, { {     0xd6,0},{     0xf0,0xd6,0} }, { {     0xd7,0},{     0xf0,0xd7,0} },        /*0d4*/
    { {     0xd8,0},{     0xf0,0xd8,0} }, { {     0xd9,0},{     0xf0,0xd9,0} }, { {     0xda,0},{     0xf0,0xda,0} }, { {     0xdb,0},{     0xf0,0xdb,0} },        /*0d8*/
    { {     0xdc,0},{     0xf0,0xdc,0} }, { {     0xdd,0},{     0xf0,0xdd,0} }, { {     0xde,0},{     0xf0,0xde,0} }, { {     0xdf,0},{     0xf0,0xdf,0} },        /*0dc*/
    { {     0xe0,0},{     0xf0,0xe0,0} }, { {     0xe1,0},{     0xf0,0xe1,0} }, { {     0xe2,0},{     0xf0,0xe2,0} }, { {     0xe3,0},{     0xf0,0xe3,0} },        /*0e0*/
    { {     0xe4,0},{     0xf0,0xe4,0} }, { {     0xe5,0},{     0xf0,0xe5,0} }, { {     0xe6,0},{     0xf0,0xe6,0} }, { {     0xe7,0},{     0xf0,0xe7,0} },        /*0e4*/
    { {     0xe8,0},{     0xf0,0xe8,0} }, { {     0xe9,0},{     0xf0,0xe9,0} }, { {     0xea,0},{     0xf0,0xea,0} }, { {     0xeb,0},{     0xf0,0xeb,0} },        /*0e8*/
    { {     0xec,0},{     0xf0,0xec,0} }, { {     0xed,0},{     0xf0,0xed,0} }, { {     0xee,0},{     0xf0,0xee,0} }, { {     0xef,0},{     0xf0,0xef,0} },        /*0ec*/
    { {          0},{               0} }, { {     0xf1,0},{     0xf0,0xf1,0} }, { {     0xf2,0},{     0xf0,0xf2,0} }, { {     0xf3,0},{     0xf0,0xf3,0} },        /*0f0*/
    { {     0xf4,0},{     0xf0,0xf4,0} }, { {     0xf5,0},{     0xf0,0xf5,0} }, { {     0xf6,0},{     0xf0,0xf6,0} }, { {     0xf7,0},{     0xf0,0xf7,0} },        /*0f4*/
    { {     0xf8,0},{     0xf0,0xf8,0} }, { {     0xf9,0},{     0xf0,0xf9,0} }, { {     0xfa,0},{     0xf0,0xfa,0} }, { {     0xfb,0},{     0xf0,0xfb,0} },        /*0f8*/
    { {     0xfc,0},{     0xf0,0xfc,0} }, { {     0xfd,0},{     0xf0,0xfd,0} }, { {     0xfe,0},{     0xf0,0xfe,0} }, { {     0xff,0},{     0xf0,0xff,0} },        /*0fc*/

    { {     0x62,0},{     0xF0,0x62,0} }, { {0xe0,0x76,0},{0xe0,0xF0,0x76,0} }, { {0xe0,0x16,0},{0xe0,0xF0,0x16,0} }, { {0xe0,0x1E,0},{0xe0,0xF0,0x1E,0} },        /*100*/
    { {0xe0,0x26,0},{0xe0,0xF0,0x26,0} }, { {0xe0,0x25,0},{0xe0,0xF0,0x25,0} }, { {0xe0,0x2E,0},{0xe0,0xF0,0x2E,0} }, { {0xe0,0x36,0},{0xe0,0xF0,0x36,0} },        /*104*/
    { {0xe0,0x3D,0},{0xe0,0xF0,0x3D,0} }, { {0xe0,0x3E,0},{0xe0,0xF0,0x3E,0} }, { {0xe0,0x46,0},{0xe0,0xF0,0x46,0} }, { {0xe0,0x45,0},{0xe0,0xF0,0x45,0} },        /*108*/
    { {0xe0,0x4E,0},{0xe0,0xF0,0x4E,0} }, { {          0},{               0} }, { {0xe0,0x66,0},{0xe0,0xF0,0x66,0} }, { {0xe0,0x0D,0},{0xe0,0xF0,0x0D,0} },        /*10c*/
    { {0xe0,0x15,0},{0xe0,0xF0,0x15,0} }, { {0xe0,0x1D,0},{0xe0,0xF0,0x1D,0} }, { {0xe0,0x24,0},{0xe0,0xF0,0x24,0} }, { {0xe0,0x2D,0},{0xe0,0xF0,0x2D,0} },        /*110*/
    { {0xe0,0x2C,0},{0xe0,0xF0,0x2C,0} }, { {0xe0,0x35,0},{0xe0,0xF0,0x35,0} }, { {0xe0,0x3C,0},{0xe0,0xF0,0x3C,0} }, { {0xe0,0x43,0},{0xe0,0xF0,0x43,0} },        /*114*/
    { {0xe0,0x44,0},{0xe0,0xF0,0x44,0} }, { {0xe0,0x4D,0},{0xe0,0xF0,0x4D,0} }, { {0xe0,0x54,0},{0xe0,0xF0,0x54,0} }, { {0xe0,0x5B,0},{0xe0,0xF0,0x5B,0} },        /*118*/
    { {     0x79,0},{     0xf0,0x79,0} }, { {     0x58,0},{     0xf0,0x58,0} }, { {0xe0,0x1C,0},{0xe0,0xF0,0x1C,0} }, { {0xe0,0x1B,0},{0xe0,0xF0,0x1B,0} },        /*11c*/
    { {0xe0,0x23,0},{0xe0,0xF0,0x23,0} }, { {0xe0,0x2B,0},{0xe0,0xF0,0x2B,0} }, { {0xe0,0x34,0},{0xe0,0xF0,0x34,0} }, { {0xe0,0x33,0},{0xe0,0xF0,0x33,0} },        /*120*/
    { {0xe0,0x3B,0},{0xe0,0xF0,0x3B,0} }, { {0xe0,0x42,0},{0xe0,0xF0,0x42,0} }, { {0xe0,0x4B,0},{0xe0,0xF0,0x4B,0} }, { {          0},{               0} },        /*124*/
    { {          0},{               0} }, { {          0},{               0} }, { {          0},{               0} }, { {          0},{               0} },        /*128*/
    { {0xe0,0x1A,0},{0xe0,0xF0,0x1A,0} }, { {0xe0,0x22,0},{0xe0,0xF0,0x22,0} }, { {0xe0,0x21,0},{0xe0,0xF0,0x21,0} }, { {0xe0,0x2A,0},{0xe0,0xF0,0x2A,0} },        /*12c*/
    { {0xe0,0x32,0},{0xe0,0xF0,0x32,0} }, { {0xe0,0x31,0},{0xe0,0xF0,0x31,0} }, { {0xe0,0x3A,0},{0xe0,0xF0,0x3A,0} }, { {          0},{               0} },        /*130*/
    { {0xe0,0x49,0},{0xe0,0xF0,0x49,0} }, { {     0x77,0},{     0xf0,0x77,0} }, { {          0},{               0} }, { {     0x57,0},{     0xf0,0x57,0} },        /*134*/
    { {     0x39,0},{     0xf0,0x39,0} }, { {          0},{               0} }, { {0xe0,0x58,0},{0xe0,0xF0,0x58,0} }, { {0xe0,0x05,0},{0xe0,0xF0,0x05,0} },        /*138*/
    { {0xe0,0x06,0},{0xe0,0xF0,0x06,0} }, { {0xe0,0x04,0},{0xe0,0xF0,0x04,0} }, { {0xe0,0x0C,0},{0xe0,0xF0,0x0C,0} }, { {0xe0,0x03,0},{0xe0,0xF0,0x03,0} },        /*13c*/
    { {0xe0,0x0B,0},{0xe0,0xF0,0x0B,0} }, { {0xe0,0x02,0},{0xe0,0xF0,0x02,0} }, { {0xe0,0x0A,0},{0xe0,0xF0,0x0A,0} }, { {0xe0,0x01,0},{0xe0,0xF0,0x01,0} },        /*140*/
    { {0xe0,0x09,0},{0xe0,0xF0,0x09,0} }, { {          0},{               0} }, { {0xe0,0x7E,0},{0xe0,0xF0,0x7E,0} }, { {     0x6E,0},{     0xf0,0x6E,0} },        /*144*/
    { {     0x63,0},{     0xf0,0x63,0} }, { {     0x6F,0},{     0xf0,0x6F,0} }, { {          0},{               0} }, { {     0x61,0},{     0xf0,0x61,0} },        /*148*/
    { {0xe0,0x73,0},{0xe0,0xF0,0x73,0} }, { {     0x6A,0},{     0xf0,0x6A,0} }, { {0xe0,0x79,0},{0xe0,0xF0,0x79,0} }, { {     0x65,0},{     0xf0,0x65,0} },        /*14c*/
    { {     0x60,0},{     0xf0,0x60,0} }, { {     0x6D,0},{     0xf0,0x6D,0} }, { {     0x67,0},{     0xf0,0x67,0} }, { {     0x64,0},{     0xf0,0x64,0} },        /*150*/
    { {     0xd4,0},{     0xf0,0xD4,0} }, { {0xe0,0x60,0},{0xe0,0xF0,0x60,0} }, { {          0},{               0} }, { {0xe0,0x78,0},{0xe0,0xF0,0x78,0} },        /*154*/
    { {0xe0,0x07,0},{0xe0,0xF0,0x07,0} }, { {0xe0,0x0F,0},{0xe0,0xF0,0x0F,0} }, { {0xe0,0x17,0},{0xe0,0xF0,0x17,0} }, { {     0x8B,0},{     0xf0,0x8B,0} },        /*158*/
    { {     0x8C,0},{     0xf0,0x8C,0} }, { {     0x8D,0},{     0xf0,0x8D,0} }, { {          0},{               0} }, { {     0x7F,0},{     0xf0,0x7F,0} },        /*15c*/
    { {          0},{               0} }, { {0xe0,0x4F,0},{0xe0,0xF0,0x4F,0} }, { {0xe0,0x56,0},{0xe0,0xF0,0x56,0} }, { {          0},{               0} },        /*160*/
    { {0xe0,0x08,0},{0xe0,0xF0,0x08,0} }, { {0xe0,0x10,0},{0xe0,0xF0,0x10,0} }, { {0xe0,0x18,0},{0xe0,0xF0,0x18,0} }, { {0xe0,0x20,0},{0xe0,0xF0,0x20,0} },        /*164*/
    { {0xe0,0x28,0},{0xe0,0xF0,0x28,0} }, { {0xe0,0x30,0},{0xe0,0xF0,0x30,0} }, { {0xe0,0x38,0},{0xe0,0xF0,0x38,0} }, { {0xe0,0x40,0},{0xe0,0xF0,0x40,0} },        /*168*/
    { {0xe0,0x48,0},{0xe0,0xF0,0x48,0} }, { {0xe0,0x50,0},{0xe0,0xF0,0x50,0} }, { {0xe0,0x57,0},{0xe0,0xF0,0x57,0} }, { {          0},{               0} },        /*16c*/
    { {0xe0,0x13,0},{0xe0,0xF0,0x13,0} }, { {0xe0,0x19,0},{0xe0,0xF0,0x19,0} }, { {0xe0,0x39,0},{0xe0,0xF0,0x39,0} }, { {0xe0,0x51,0},{0xe0,0xF0,0x51,0} },        /*170*/
    { {0xe0,0x53,0},{0xe0,0xF0,0x53,0} }, { {0xe0,0x5C,0},{0xe0,0xF0,0x5C,0} }, { {          0},{               0} }, { {0xe0,0x62,0},{0xe0,0xF0,0x62,0} },        /*174*/
    { {0xe0,0x63,0},{0xe0,0xF0,0x63,0} }, { {0xe0,0x64,0},{0xe0,0xF0,0x64,0} }, { {0xe0,0x65,0},{0xe0,0xF0,0x65,0} }, { {0xe0,0x67,0},{0xe0,0xF0,0x67,0} },        /*178*/
    { {0xe0,0x68,0},{0xe0,0xF0,0x68,0} }, { {0xe0,0x6A,0},{0xe0,0xF0,0x6A,0} }, { {0xe0,0x6D,0},{0xe0,0xF0,0x6D,0} }, { {0xe0,0x6E,0},{0xe0,0xF0,0x6E,0} },        /*17c*/

    { {          0},{               0} }, { {          0},{               0} }, { {          0},{               0} }, { {          0},{               0} },        /*180*/
    { {          0},{               0} }, { {          0},{               0} }, { {          0},{               0} }, { {          0},{               0} },        /*184*/
    { {          0},{               0} }, { {          0},{               0} }, { {          0},{               0} }, { {          0},{               0} },        /*188*/
    { {          0},{               0} }, { {          0},{               0} }, { {          0},{               0} }, { {          0},{               0} },        /*18c*/
    { {          0},{               0} }, { {          0},{               0} }, { {          0},{               0} }, { {          0},{               0} },        /*190*/
    { {          0},{               0} }, { {          0},{               0} }, { {          0},{               0} }, { {          0},{               0} },        /*194*/
    { {          0},{               0} }, { {          0},{               0} }, { {          0},{               0} }, { {          0},{               0} },        /*198*/
    { {          0},{               0} }, { {          0},{               0} }, { {          0},{               0} }, { {          0},{               0} },        /*19c*/
    { {          0},{               0} }, { {          0},{               0} }, { {          0},{               0} }, { {          0},{               0} },        /*1a0*/
    { {          0},{               0} }, { {          0},{               0} }, { {          0},{               0} }, { {          0},{               0} },        /*1a4*/
    { {          0},{               0} }, { {          0},{               0} }, { {          0},{               0} }, { {          0},{               0} },        /*1a8*/
    { {          0},{               0} }, { {          0},{               0} }, { {          0},{               0} }, { {          0},{               0} },        /*1ac*/
    { {          0},{               0} }, { {          0},{               0} }, { {          0},{               0} }, { {          0},{               0} },        /*1c0*/
    { {          0},{               0} }, { {          0},{               0} }, { {          0},{               0} }, { {          0},{               0} },        /*1c4*/
    { {          0},{               0} }, { {          0},{               0} }, { {          0},{               0} }, { {          0},{               0} },        /*1c8*/
    { {          0},{               0} }, { {          0},{               0} }, { {          0},{               0} }, { {          0},{               0} },        /*1cc*/
    { {          0},{               0} }, { {          0},{               0} }, { {          0},{               0} }, { {          0},{               0} },        /*1d0*/
    { {          0},{               0} }, { {          0},{               0} }, { {          0},{               0} }, { {          0},{               0} },        /*1d4*/
    { {          0},{               0} }, { {          0},{               0} }, { {          0},{               0} }, { {          0},{               0} },        /*1d8*/
    { {          0},{               0} }, { {          0},{               0} }, { {          0},{               0} }, { {          0},{               0} },        /*1dc*/
    { {          0},{               0} }, { {0xe0,0xe1,0},{0xe0,0xF0,0xE1,0} }, { {          0},{               0} }, { {          0},{               0} },        /*1e0*/
    { {          0},{               0} }, { {          0},{               0} }, { {          0},{               0} }, { {          0},{               0} },        /*1e4*/
    { {          0},{               0} }, { {          0},{               0} }, { {          0},{               0} }, { {          0},{               0} },        /*1e8*/
    { {          0},{               0} }, { {          0},{               0} }, { {0xe0,0xee,0},{0xe0,0xF0,0xEE,0} }, { {          0},{               0} },        /*1ec*/
    { {          0},{               0} }, { {0xe0,0xf1,0},{0xe0,0xF0,0xF1,0} }, { {          0},{               0} }, { {          0},{               0} },        /*1f0*/
    { {          0},{               0} }, { {          0},{               0} }, { {          0},{               0} }, { {          0},{               0} },        /*1f4*/
    { {          0},{               0} }, { {          0},{               0} }, { {          0},{               0} }, { {          0},{               0} },        /*1f8*/
    { {          0},{               0} }, { {          0},{               0} }, { {0xe0,0xfe,0},{0xe0,0xF0,0xFE,0} }, { {0xe0,0xff,0},{0xe0,0xF0,0xFF,0} }         /*1fc*/
  // clang-format on
};

#ifdef ENABLE_KEYBOARD_AT_LOG
int keyboard_at_do_log = ENABLE_KEYBOARD_AT_LOG;

static void
keyboard_at_log(const char *fmt, ...)
{
    va_list ap;

    if (keyboard_at_do_log) {
        va_start(ap, fmt);
        pclog_ex(fmt, ap);
        va_end(ap);
    }
}
#else
#    define keyboard_at_log(fmt, ...)
#endif

static void
keyboard_at_set_scancode_set(void)
{
    switch (keyboard_mode) {
        default:
        case 0x01:
            keyboard_set_table(scancode_set1);
            break;

        case 0x02:
            keyboard_set_table(scancode_set2);
            break;

        case 0x03:
            keyboard_set_table(scancode_set3);
            break;
    }
}

static void
add_data_vals(atkbc_dev_t *dev, uint8_t *val, uint8_t len)
{
    for (uint8_t i = 0; i < len; i++)
        kbc_at_dev_queue_add(dev, val[i], 1);
}

static void
add_data_kbd(uint16_t val)
{
    atkbc_dev_t *dev = SavedKbd;
    uint8_t  fake_shift[4] = { 0 };
    uint8_t  num_lock = 0;
    uint8_t  shift_states = 0;

    dev->ignore = 1;

    keyboard_get_states(NULL, &num_lock, NULL);
    shift_states = keyboard_get_shift() & STATE_SHIFT_MASK;

    switch (val) {
        case FAKE_LSHIFT_ON:
            keyboard_at_log("%s: Fake left shift on, scan code: ", dev->name);
            if (num_lock) {
                if (shift_states) {
                    keyboard_at_log("N/A (one or both shifts on)\n");
                    break;
                } else {
                    /* Num lock on and no shifts are pressed, send non-inverted fake shift. */
                    switch (keyboard_mode & 0x02) {
                        case 1:
                            keyboard_at_log("E0 2A\n");
                            fake_shift[0] = 0xe0;
                            fake_shift[1] = 0x2a;
                            add_data_vals(dev, fake_shift, 2);
                            break;

                        case 2:
                            keyboard_at_log("E0 12\n");
                            fake_shift[0] = 0xe0;
                            fake_shift[1] = 0x12;
                            add_data_vals(dev, fake_shift, 2);
                            break;

                        default:
                            keyboard_at_log("N/A (scan code set %i)\n", keyboard_mode & 0x02);
                            break;
                    }
                }
            } else {
                if (shift_states & STATE_LSHIFT) {
                    /* Num lock off and left shift pressed. */
                    switch (keyboard_mode & 0x02) {
                        case 1:
                            keyboard_at_log("E0 AA\n");
                            fake_shift[0] = 0xe0;
                            fake_shift[1] = 0xaa;
                            add_data_vals(dev, fake_shift, 2);
                            break;

                        case 2:
                            keyboard_at_log("E0 F0 12\n");
                            fake_shift[0] = 0xe0;
                            fake_shift[1] = 0xf0;
                            fake_shift[2] = 0x12;
                            add_data_vals(dev, fake_shift, 3);
                            break;

                        default:
                            keyboard_at_log("N/A (scan code set %i)\n", keyboard_mode & 0x02);
                            break;
                    }
                }
                if (shift_states & STATE_RSHIFT) {
                    /* Num lock off and right shift pressed. */
                    switch (keyboard_mode & 0x02) {
                        case 1:
                            keyboard_at_log("E0 B6\n");
                            fake_shift[0] = 0xe0;
                            fake_shift[1] = 0xb6;
                            add_data_vals(dev, fake_shift, 2);
                            break;

                        case 2:
                            keyboard_at_log("E0 F0 59\n");
                            fake_shift[0] = 0xe0;
                            fake_shift[1] = 0xf0;
                            fake_shift[2] = 0x59;
                            add_data_vals(dev, fake_shift, 3);
                            break;

                        default:
                            keyboard_at_log("N/A (scan code set %i)\n", keyboard_mode & 0x02);
                            break;
                    }
                }
                keyboard_at_log(shift_states ? "" : "N/A (both shifts off)\n");
            }
            break;

        case FAKE_LSHIFT_OFF:
            keyboard_at_log("%s: Fake left shift on, scan code: ", dev->name);
            if (num_lock) {
                if (shift_states) {
                    keyboard_at_log("N/A (one or both shifts on)\n");
                    break;
                } else {
                    /* Num lock on and no shifts are pressed, send non-inverted fake shift. */
                    switch (keyboard_mode & 0x02) {
                        case 1:
                            keyboard_at_log("E0 AA\n");
                            fake_shift[0] = 0xe0;
                            fake_shift[1] = 0xaa;
                            add_data_vals(dev, fake_shift, 2);
                            break;

                        case 2:
                            keyboard_at_log("E0 F0 12\n");
                            fake_shift[0] = 0xe0;
                            fake_shift[1] = 0xf0;
                            fake_shift[2] = 0x12;
                            add_data_vals(dev, fake_shift, 3);
                            break;

                        default:
                            keyboard_at_log("N/A (scan code set %i)\n", keyboard_mode & 0x02);
                            break;
                    }
                }
            } else {
                if (shift_states & STATE_LSHIFT) {
                    /* Num lock off and left shift pressed. */
                    switch (keyboard_mode & 0x02) {
                        case 1:
                            keyboard_at_log("E0 2A\n");
                            fake_shift[0] = 0xe0;
                            fake_shift[1] = 0x2a;
                            add_data_vals(dev, fake_shift, 2);
                            break;

                        case 2:
                            keyboard_at_log("E0 12\n");
                            fake_shift[0] = 0xe0;
                            fake_shift[1] = 0x12;
                            add_data_vals(dev, fake_shift, 2);
                            break;

                        default:
                            keyboard_at_log("N/A (scan code set %i)\n", keyboard_mode & 0x02);
                            break;
                    }
                }
                if (shift_states & STATE_RSHIFT) {
                    /* Num lock off and right shift pressed. */
                    switch (keyboard_mode & 0x02) {
                        case 1:
                            keyboard_at_log("E0 36\n");
                            fake_shift[0] = 0xe0;
                            fake_shift[1] = 0x36;
                            add_data_vals(dev, fake_shift, 2);
                            break;

                        case 2:
                            keyboard_at_log("E0 59\n");
                            fake_shift[0] = 0xe0;
                            fake_shift[1] = 0x59;
                            add_data_vals(dev, fake_shift, 2);
                            break;

                        default:
                            keyboard_at_log("N/A (scan code set %i)\n", keyboard_mode & 0x02);
                            break;
                    }
                }
                keyboard_at_log(shift_states ? "" : "N/A (both shifts off)\n");
            }
            break;

        default:
            kbc_at_dev_queue_add(dev, val, 1);
            break;
    }

    dev->ignore = 0;
}

void
keyboard_at_clear_data(void *priv)
{
    atkbc_dev_t *dev = (atkbc_dev_t *) priv;

    dev->flags &= ~FLAG_CTRLDAT;
}

static void
keyboard_at_set_defaults(atkbc_dev_t *dev)
{
    dev->rate = 1;

    keyboard_set3_all_break  = 0;
    keyboard_set3_all_repeat = 0;
    memset(keyboard_set3_flags, 0, 512);

    keyboard_mode = 0x02;
    keyboard_at_set_scancode_set();
}

static void
keyboard_at_bat(void *priv)
{
    atkbc_dev_t *dev = (atkbc_dev_t *) priv;

    if (bat_counter == 0x0000) {
        keyboard_at_set_defaults(dev);

        keyboard_scan = 1;

        kbc_at_dev_queue_add(dev, 0xaa, 0);
    } else {
        bat_counter--;
        dev->state = DEV_STATE_EXECUTE_BAT;
    }
}

static void
keyboard_at_invalid_cmd(atkbc_dev_t *dev)
{
    keyboard_at_log("%s: Invalid command [%02X]\n", dev->name, dev->port->dat);
    kbc_at_dev_queue_add(dev, inv_cmd_response, 0);
}


static void
keyboard_at_write(void *priv)
{
    atkbc_dev_t *dev = (atkbc_dev_t *) priv;
    uint8_t val;

    if (dev->port == NULL)
        return;

    val = dev->port->dat;

    dev->state = DEV_STATE_MAIN_OUT;

    if ((val < 0xed) && (dev->flags & FLAG_CTRLDAT)) {
        dev->flags &= ~FLAG_CTRLDAT;

        switch (dev->command) {
            case 0xed: /* Set/reset LEDs */
                kbc_at_dev_queue_add(dev, 0xfa, 0);
                keyboard_at_log("%s: Set/reset LEDs [%02X]\n", dev->name, val);
                break;

            case 0xf0: /* Get/set scancode set */
                kbc_at_dev_queue_add(dev, (val > 3) ? 0xfe : 0xfa, 0);
                switch (val) {
                    case 0x00:
                        keyboard_at_log("%s: Get scan code set [%02X]\n", dev->name, keyboard_mode);
                        kbc_at_dev_queue_add(dev, keyboard_mode, 0);
                        break;
                    case 0x01 ... 0x03:
                        keyboard_mode = val;
                        keyboard_at_log("%s: Set scan code set [%02X]\n", dev->name, keyboard_mode);
                        keyboard_at_set_scancode_set();
                        break;
                    default:
                        /* Fatal so any instance of anything attempting to set scan code > 3 can be reported to us. */
                        fatal("%s: Scan code set [%02X] invalid, resend\n", dev->name, val);
                        dev->flags |= FLAG_CTRLDAT;
                        dev->state = DEV_STATE_MAIN_WANT_IN;
                        break;
                }
                break;

            case 0xf3: /* set typematic rate/delay */
                if (val & 0x80) {
                    keyboard_at_log("%s: Set typematic rate/delay [%02X] has bit 7 set - invalid\n", dev->name, val);
                    dev->flags |= FLAG_CTRLDAT;      /* Resend = keep waiting for parameter. */
                    kbc_at_dev_queue_add(dev, 0xfe, 0); /* Command response */
                    dev->state = DEV_STATE_MAIN_WANT_IN;
                } else {
                    dev->rate = val;
                    kbc_at_dev_queue_add(dev, 0xfa, 0); /* Command response */
                    keyboard_at_log("%s: Set typematic rate/delay [%02X]\n", dev->name, val);
                }
                break;

            default:
                fatal("%s: Parameter [%02X] for invalid command [%02X] - possibly memory corruption!\n", dev->name, val, dev->command);
                kbc_at_dev_queue_add(dev, 0xfe, 0);
        }
    } else {
        if (dev->flags & FLAG_CTRLDAT) {
            /* Special case - another command during another command that wants input - proceed
               as normal but do not cancel the command (so keep waiting for input), unless the
               command in progress is ED (Set/reset LEDs). */
            if (val == 0xed) {
                keyboard_scan = 1;
                dev->flags &= ~FLAG_CTRLDAT;
            } else
                dev->state = DEV_STATE_MAIN_WANT_IN;
        }

        switch (val) {
            case 0xed: /* set/reset LEDs */
                dev->command = val;
                keyboard_at_log("%s: set/reset LEDs\n", dev->name);
                dev->flags |= FLAG_CTRLDAT;
                kbc_at_dev_queue_add(dev, 0xfa, 0); /* ACK for command byte */
                dev->state = DEV_STATE_MAIN_WANT_IN;
                break;

            case 0xee: /* diagnostic echo */
                keyboard_at_log("%s: ECHO\n", dev->name);
                kbc_at_dev_queue_add(dev, 0xee, 0);
                break;

            case 0xef: /* Invalid command */
            case 0xf1: /* Invalid command */
                keyboard_at_log("%s: Invalid command [%02X]\n", dev->name, dev->port->dat);
                kbc_at_dev_queue_add(dev, inv_cmd_response, 0);
                break;

            case 0xf0: /* get/set scan code set */
                if (dev->type & FLAG_PS2) {
                    dev->command = val;
                    keyboard_at_log("%s: scan code set\n", dev->name);
                    dev->flags |= FLAG_CTRLDAT;
                    kbc_at_dev_queue_add(dev, 0xfa, 0); /* ACK for command byte */
                    dev->state = DEV_STATE_MAIN_WANT_IN;
                } else
                    keyboard_at_invalid_cmd(dev);
                break;

            case 0xf2: /* read ID */
                keyboard_at_log("%s: read keyboard id\n", dev->name);
                /* TODO: After keyboard type selection is implemented, make this
                         return the correct keyboard ID for the selected type. */
                kbc_at_dev_queue_add(dev, 0xfa, 0);
                for (uint8_t i = 0; i < 4; i++) {
                    if (id_bytes[dev->type][i] == 0)
                        break;

                    kbc_at_dev_queue_add(dev, id_bytes[dev->type][i], 0);
                }
                break;

            case 0xf3: /* set command mode */
                dev->command = val;
                keyboard_at_log("%s: set typematic rate/delay\n", dev->name);
                dev->flags |= FLAG_CTRLDAT;
                kbc_at_dev_queue_add(dev, 0xfa, 0); /* ACK for command byte */
                dev->state = DEV_STATE_MAIN_WANT_IN;
                break;

            case 0xf4: /* enable */
                keyboard_at_log("%s: enable keyboard\n", dev->name);
                keyboard_scan = 1;
                kbc_at_dev_queue_add(dev, 0xfa, 0);
                break;

            case 0xf5: /* set defaults and disable keyboard */
            case 0xf6: /* set defaults */
                keyboard_at_log("%s: set defaults%s\n",
                                dev->name, (val == 0xf6) ? "" : " and disable keyboard");
                keyboard_scan = !(val & 0x01);
                keyboard_at_log("%s: val = %02X, keyboard_scan = %i\n",
                                dev->name, val, keyboard_scan);
                kbc_at_dev_queue_add(dev, 0xfa, 0);

                keyboard_set3_all_break  = 0;
                keyboard_set3_all_repeat = 0;
                memset(keyboard_set3_flags, 0, 512);

                keyboard_mode = 0x02;
                keyboard_at_set_scancode_set();
                break;

            case 0xf7: /* set all keys to repeat */
                if (dev->type & FLAG_PS2) {
                    keyboard_at_log("%s: set all keys to repeat\n", dev->name);
                    kbc_at_dev_queue_add(dev, 0xfa, 0);
                    keyboard_set3_all_break = 1;
                } else
                    keyboard_at_invalid_cmd(dev);
                break;

            case 0xf8: /* set all keys to give make/break codes */
                if (dev->type & FLAG_PS2) {
                    keyboard_at_log("%s: set all keys to give make/break codes\n", dev->name);
                    kbc_at_dev_queue_add(dev, 0xfa, 0);
                    keyboard_set3_all_break = 1;
                } else
                    keyboard_at_invalid_cmd(dev);
                break;

            case 0xf9: /* set all keys to give make codes only */
                if (dev->type & FLAG_PS2) {
                    keyboard_at_log("%s: set all keys to give make codes only\n", dev->name);
                    kbc_at_dev_queue_add(dev, 0xfa, 0);
                    keyboard_set3_all_break = 0;
                } else
                    keyboard_at_invalid_cmd(dev);
                break;

            case 0xfa: /* set all keys to repeat and give make/break codes */
                if (dev->type & FLAG_PS2) {
                    keyboard_at_log("%s: set all keys to repeat and give make/break codes\n", dev->name);
                    kbc_at_dev_queue_add(dev, 0xfa, 0);
                    keyboard_set3_all_repeat = 1;
                    keyboard_set3_all_break  = 1;
                } else
                    keyboard_at_invalid_cmd(dev);
                break;

            /* TODO: Actually implement these commands. */
            case 0xfb: /* set some keys to repeat */
                keyboard_at_log("%s: set some keys to repeat\n", dev->name);
                kbc_at_dev_queue_add(dev, inv_cmd_response, 0);
                break;

            case 0xfc: /* set some keys to give make/break codes */
                keyboard_at_log("%s: set some keys to give make/break codes\n", dev->name);
                kbc_at_dev_queue_add(dev, inv_cmd_response, 0);
                break;

            case 0xfd: /* set some keys to give make codes only */
                keyboard_at_log("%s: set some keys to give make codes only\n", dev->name);
                kbc_at_dev_queue_add(dev, inv_cmd_response, 0);
                break;

            /* TODO: This is supposed to resend multiple bytes after some commands. */
            case 0xfe: /* resend last scan code */
                keyboard_at_log("%s: resend last scan code\n", dev->name);
                kbc_at_dev_queue_add(dev, dev->last_scan_code, 0);
                break;

            case 0xff: /* reset */
                kbc_at_dev_reset(dev, 1);
                bat_counter = 1000;
                break;

            default:
                kbc_at_dev_queue_add(dev, 0xfe, 0);
        }
    }
}

/*
 * Initialize the device for use by the user.
 *
 * We also get called from the various machines.
 */
void *
keyboard_at_init(const device_t *info)
{
    atkbc_dev_t *dev = kbc_at_dev_init(DEV_KBD);

    dev->name = info->name;
    /* Key 14  = Japanese key next to backspace, scan code:                13 (Yen 7D);
       Key 29  = US backslash, scan code:                                  5C (Backslash 2B);
       Key 42  = European backslash, scan code:                            53 (Backslash 2B);
       Key 45  = European key next to left shift, scan code:               13 (Key 56);
       Key 56  = Japanese key next to right shift, scan code:              5C (Backslash 73);
       Key 59  = Japanese key between left Ctrl and left Alt, scan code:   85 (Muhenkan 7B);
       Key 63  = Japanese key between right Ctrl and right Alt, scan code: 86 (Henkan/Zenkouho 79);
       Key 65? = Japanese key between right Ctrl and right Alt, scan code: 87 (Hiragana/Katakana 70).
     */
    dev->type = FLAG_PS2 | KBD_102_KEY /* device_get_config_int("type") */;

    keyboard_at_log("%s: type=%d\n", dev->name, dev->type);

    dev->process_cmd = keyboard_at_write;
    dev->execute_bat = keyboard_at_bat;

    dev->scan        = &keyboard_scan;

    dev->fifo_mask   = FIFO_SIZE - 1;

    if (dev->port != NULL) {
        kbc_at_dev_reset(dev, 0);
        bat_counter = 0x0000;
    }

    keyboard_send = add_data_kbd;
    SavedKbd = dev;

    inv_cmd_response = (dev->type & FLAG_PS2) ? 0xfe : 0xfa;

    /* Return our private data to the I/O layer. */
    return dev;
}

static void
keyboard_at_close(void *priv)
{
    atkbc_dev_t *dev = (atkbc_dev_t *) priv;

    keyboard_scan = 0;
    keyboard_send = NULL;

    /* Disable the scancode maps. */
    keyboard_set_table(NULL);

    SavedKbd = NULL;

    free(dev);
}

static const device_config_t keyboard_at_config[] = {
  // clang-format off
    {
        .name = "type",
        .description = "Type",
        .type = CONFIG_SELECTION,
        .default_string = "",
        .default_int = 2,
        .file_filter = "",
        .spinner = { 0 },
        .selection = {
            { .description = "AT 84-key",          .value = FLAG_AT  | KBD_84_KEY  },
            { .description = "AT 101/102/106-key", .value = FLAG_AT  | KBD_101_KEY },
            { .description = "AT Korean",          .value = FLAG_AT  | KBD_KOREAN  },
            { .description = "PS/2 101-key",       .value = FLAG_PS2 | KBD_101_KEY },
            { .description = "PS/2 102-key",       .value = FLAG_PS2 | KBD_102_KEY },
            { .description = "PS/2 106-key JIS",   .value = FLAG_PS2 | KBD_JIS     },
            { .description = "PS/2 Korean",        .value = FLAG_PS2 | KBD_KOREAN  },
            { .description = ""                                                    }
        }
    },
    {
        .name = "", .description = "", .type = CONFIG_END
    }
  // clang-format on
};

/* TODO: Add more keyboard types. */
const device_t keyboard_at_generic_device = {
    .name          = "Standard AT or PS/2 Keyboard",
    .internal_name = "ps2",
    .flags         = DEVICE_PS2,
    .local         = 0,
    .init          = keyboard_at_init,
    .close         = keyboard_at_close,
    .reset         = NULL,
    { .poll = NULL },
    .speed_changed = NULL,
    .force_redraw  = NULL,
    .config        = keyboard_at_config
};
